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; +} |