|
From: <mr...@mr...> - 2005-03-09 12:34:03
|
# This is a BitKeeper generated diff -Nru style patch.
#
# src/tcp/tcp.c
# 2005/03/09 13:32:35+01:00 mr...@fo... +211 -0
# =
# src/tcp/TC2Module
# 2005/03/09 13:32:35+01:00 mr...@fo... +6 -0
# =
# ChangeSet
# 2005/03/09 13:32:35+01:00 mr...@fo... =
# new url handler tcp:
# tcp:addr:port attempts to connect
# tcp::port listens on any interface
# tcp:addr:port?listen listens on addr only
# =
# src/tcp/tcp.c
# 2005/03/09 13:32:35+01:00 mr...@fo... +0 -0
# BitKeeper file /home/mru/src/tc2-modules/src/tcp/tcp.c
# =
# src/tcp/TC2Module
# 2005/03/09 13:32:35+01:00 mr...@fo... +0 -0
# BitKeeper file /home/mru/src/tc2-modules/src/tcp/TC2Module
# =
# TC2Package
# 2005/03/09 13:32:34+01:00 mr...@fo... +1 -0
# add tcp: url handler
# =
diff -Nru a/TC2Package b/TC2Package
--- a/TC2Package 2005-03-09 13:33:52 +01:00
+++ b/TC2Package 2005-03-09 13:33:52 +01:00
@@ -11,4 +11,5 @@
module src/perl
module src/png
module src/shell
+module src/tcp
module src/url
diff -Nru a/src/tcp/TC2Module b/src/tcp/TC2Module
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/src/tcp/TC2Module 2005-03-09 13:33:52 +01:00
@@ -0,0 +1,6 @@
+module tcp
+name "TC2/URL/tcp"
+version 0.1.0
+tc2version 0.6.0
+implement "URL/tcp" "open" tcp_open
+sources tcp.c
diff -Nru a/src/tcp/tcp.c b/src/tcp/tcp.c
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/src/tcp/tcp.c 2005-03-09 13:33:52 +01:00
@@ -0,0 +1,211 @@
+/**
+ Copyright (C) 2005 Michael Ahlberg, M=C3=A5ns Rullg=C3=A5rd
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without
+ restriction, including without limitation the rights to use, copy,
+ modify, merge, publish, distribute, sublicense, and/or sell copies
+ of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+**/
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <tctypes.h>
+#include <tcstring.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <errno.h>
+#include <tcalloc.h>
+#include <tcp_tc2.h>
+
+typedef struct tcp_stream {
+ int socket;
+ uint64_t pos;
+} tcp_stream_t;
+
+extern int
+tcp_read(void *buf, size_t size, size_t count, url_t *u)
+{
+ tcp_stream_t *tcp =3D u->private;
+ size_t s =3D size * count;
+ ssize_t r;
+
+ r =3D read(tcp->socket, buf, s);
+ if(r < 0)
+ return -1;
+
+ tcp->pos +=3D r;
+
+ return r / size;
+}
+
+extern int
+tcp_write(void *buf, size_t size, size_t count, url_t *u)
+{
+ tcp_stream_t *tcp =3D u->private;
+ int s;
+
+ s =3D write(tcp->socket, buf, size * count);
+ if(s < 0)
+ return s;
+
+ tcp->pos +=3D s;
+
+ return s / size;
+}
+
+extern int
+tcp_seek(url_t *u, int64_t offset, int how)
+{
+ return -1;
+}
+
+extern uint64_t
+tcp_tell(url_t *u)
+{
+ tcp_stream_t *tcp =3D u->private;
+ return tcp->pos;
+}
+
+extern int
+tcp_close(url_t *u)
+{
+ tcfree(u);
+ return 0;
+}
+
+static void
+tcp_free(void *p)
+{
+ url_t *u =3D p;
+ tcp_stream_t *tcp =3D u->private;
+ close(tcp->socket);
+}
+
+extern url_t *
+tcp_open(char *url, char *mode)
+{
+ struct sockaddr_in sa;
+ struct hostent *hn;
+ tcp_stream_t *tcp;
+ uint32_t addr;
+ char *host;
+ url_t *u;
+ int srv =3D 0;
+ char *pp;
+ int port;
+ int sock;
+ int i;
+
+ host =3D strdupa(url);
+
+ if(!strncmp(host, "tcp:", 4))
+ host +=3D 4;
+
+ while(*host =3D=3D '/')
+ host++;
+
+ if(!(pp =3D strchr(host, ':')))
+ return NULL;
+
+ *pp++ =3D 0;
+ port =3D strtol(pp, &pp, 0);
+
+ if(*pp++ =3D=3D '?'){
+ while(pp && *pp){
+ char *np =3D strchr(pp, '&');
+ char *v =3D strchr(pp, '=3D');
+ if(np)
+ *np++ =3D 0;
+ if(v)
+ *v++ =3D 0;
+ if(!strcmp(pp, "listen"))
+ srv =3D 1;
+ pp =3D np;
+ }
+ }
+
+ if(*host){
+ if(!(hn =3D gethostbyname(host)))
+ return NULL;
+ addr =3D *(uint32_t *) hn->h_addr;
+ } else {
+ addr =3D htonl(INADDR_ANY);
+ srv =3D 1;
+ }
+
+ if((sock =3D socket(PF_INET, SOCK_STREAM, 0)) < 0)
+ return NULL;
+
+ i =3D 1;
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
+
+ sa.sin_family =3D AF_INET;
+ sa.sin_port =3D htons(port);
+ sa.sin_addr.s_addr =3D addr;
+
+ if(!srv){
+ if(connect(sock, (struct sockaddr *) &sa, sizeof(sa)) < 0){
+ tc2_print("TCP", TC2_PRINT_VERBOSE, "connect(%s:%i): %s\n",
+ host, port, strerror(errno));
+ goto err;
+ }
+ } else {
+ int asock;
+
+ if(bind(sock, (struct sockaddr *) &sa, sizeof(sa)) < 0){
+ tc2_print("TCP", TC2_PRINT_VERBOSE, "bind(%s:%i): %s\n",
+ host, port, strerror(errno));
+ goto err;
+ }
+ if(listen(sock, 4) < 0){
+ tc2_print("TCP", TC2_PRINT_VERBOSE, "listen(%s:%i): %s\n",
+ host, port, strerror(errno));
+ goto err;
+ }
+
+ asock =3D accept(sock, (struct sockaddr *) &sa, &i);
+ if(asock < 0){
+ tc2_print("TCP", TC2_PRINT_VERBOSE, "accept(%s:%i): %s\n",
+ host, port, strerror(errno));
+ goto err;
+ }
+
+ close(sock);
+ sock =3D asock;
+ }
+
+ tcp =3D calloc(1, sizeof(*tcp));
+ tcp->socket =3D sock;
+
+ u =3D tcallocdz(sizeof(*u), NULL, tcp_free);
+ if(*mode =3D=3D 'r' || mode[1] =3D=3D '+')
+ u->read =3D tcp_read;
+ if(*mode =3D=3D 'w' || mode[1] =3D=3D '+')
+ u->write =3D tcp_write;
+ u->seek =3D tcp_seek;
+ u->tell =3D tcp_tell;
+ u->close =3D tcp_close;
+ u->private =3D tcp;
+
+ return u;
+
+err:
+ close(sock);
+ return NULL;
+}
|