| version 1.4, 2003/11/20 11:55:16 |
version 1.5, 2006/08/14 10:03:21 |
|
|
| #include <stdio.h> |
#include <stdio.h> |
| #include <stdlib.h> |
#include <stdlib.h> |
| #include <string.h> |
#include <string.h> |
| |
#include <unistd.h> |
| #include <sys/time.h> |
#include <sys/time.h> |
| #include <sys/types.h> |
#include <sys/types.h> |
| #include <unistd.h> |
|
| #include <sys/socket.h> |
#include <sys/socket.h> |
| #include <netinet/in.h> |
#include <netinet/in.h> |
| #include <netdb.h> |
|
| #include <arpa/inet.h> |
#include <arpa/inet.h> |
| |
#include <netdb.h> |
| |
|
| |
#include <platon/macros.h> |
| #include <platon/net/connection.h> |
#include <platon/net/connection.h> |
| |
|
| static char*__net_connection_buffer=NULL; |
enum read_modes |
| |
{ |
| |
READ_NORMAL, |
| |
READ_BLOCKED, |
| |
READ_FULL |
| |
}; |
| |
|
| |
struct line_buffer |
| |
{ |
| |
int handle; |
| |
int buf_used; |
| |
int buf_size; |
| |
void *buffer; |
| |
}; |
| |
|
| |
static int n_line_buffers = 0; |
| |
static struct line_buffer *linebuf = NULL; |
| |
|
| |
static void linebuf_out_of_memory(void) /* {{{ */ |
| |
{ |
| |
fputs(__FILE__, stderr); |
| |
fputs("out of memory\n", stderr); |
| |
exit(128); |
| |
} /* }}} */ |
| |
|
| |
static int linebuf_append(int handle, void *buffer, int size) /* {{{ */ |
| |
{ |
| |
register int i, handle_idx = -1; |
| |
|
| |
for (i = 0; i < n_line_buffers; i++) |
| |
if (linebuf[i].handle == handle) |
| |
handle_idx = i; |
| |
|
| |
if (handle_idx == -1) { |
| |
linebuf = (struct line_buffer *) realloc((void *) linebuf, |
| |
(i + 1) * sizeof(struct line_buffer)); |
| |
if (linebuf == NULL) |
| |
linebuf_out_of_memory(); |
| |
|
| |
linebuf[i].handle = handle; |
| |
linebuf[i].buf_used = 0; |
| |
linebuf[i].buf_size = 0; |
| |
linebuf[i].buffer = NULL; |
| |
} |
| |
|
| |
if (linebuf[i].buf_size - linebuf[i].buf_used < size |
| |
|| linebuf[i].buffer == NULL) { |
| |
linebuf[i].buf_size = linebuf[i].buf_used + max(size, 20); |
| |
linebuf[i].buffer = (char *) realloc((void *) linebuf[i].buffer, |
| |
linebuf[i].buf_size * sizeof(char)); |
| |
if (linebuf[i].buffer == NULL) |
| |
linebuf_out_of_memory(); |
| |
} |
| |
|
| |
memcpy((void *) ((char *) linebuf[i].buffer + linebuf[i].buf_used), |
| |
buffer, size); |
| |
linebuf[i].buf_used += size; |
| |
|
| int net_connection_connect(const char*host,int port){ |
return size; |
| |
} /* }}} */ |
| |
|
| |
static int linebuf_fetch(int handle, void *buffer, int size) /* {{{ */ |
| |
{ |
| |
register int i, handle_idx = -1, bytes_fetched; |
| |
|
| |
for (i = 0; i < n_line_buffers; i++) |
| |
if (linebuf[i].handle == handle) |
| |
handle_idx = i; |
| |
|
| |
if (handle_idx == -1) |
| |
return 0; |
| |
|
| |
bytes_fetched = min(linebuf[i].buf_used, size); |
| |
memcpy(buffer, linebuf[i].buffer, bytes_fetched); |
| |
linebuf[i].buf_used -= bytes_fetched; |
| |
|
| |
return bytes_fetched; |
| |
} /* }}} */ |
| |
|
| |
int net_connection_open(const char *host, int port) /* {{{ */ |
| |
{ |
| int sock; |
int sock; |
| struct sockaddr_in sin; |
struct sockaddr_in sin; |
| struct hostent*he; |
struct hostent *he; |
| |
|
| he=gethostbyname(host); |
he = gethostbyname(host); |
| #if NET_CONNECTION_DEBUG |
#if NET_CONNECTION_DEBUG |
| fprintf(stderr,"net_connection_connect()\n"); |
fprintf(stderr, "net_connection_connect()\n"); |
| if(he==NULL) |
if (he == NULL) |
| fprintf(stderr," ERROR: Unknown host. [%s]\n",host); |
fprintf(stderr, " ERROR: unknown host: %s\n", host); |
| else |
else |
| fprintf(stderr," OK: Host found. [%s]\n",host); |
fprintf(stderr, " OK: host found: %s\n",host); |
| #endif |
#endif |
| if(he==NULL)return(-1); |
if (he == NULL) |
| |
return -1; |
| |
|
| if(port<=0){ |
if (port <= 0) { |
| #if NET_CONNECTION_DEBUG |
#if NET_CONNECTION_DEBUG |
| fprintf(stderr," WARNING: Bad port (%d) changed to default (%d).\n", |
fprintf(stderr, " ERROR: bad port: %d\n", port); |
| port, NET_CONNECTION_PORT); |
|
| #endif |
#endif |
| port=NET_CONNECTION_PORT; |
return -1; |
| } |
} |
| |
|
| sin.sin_family=AF_INET; |
sock = socket(PF_INET, SOCK_STREAM, 0); |
| sin.sin_addr.s_addr=*((unsigned int*)he->h_addr); |
|
| sin.sin_port=htons(port); |
|
| sock=socket(PF_INET,SOCK_STREAM,0); |
|
| #if NET_CONNECTION_DEBUG |
#if NET_CONNECTION_DEBUG |
| if(sock==-1) |
if (sock == -1) |
| fprintf(stderr," ERROR: Can't create socket.\n"); |
fprintf(stderr, " ERROR: can't create socket\n"); |
| else |
else |
| fprintf(stderr," OK: Socket created.\n"); |
fprintf(stderr, " OK: socket created\n"); |
| #endif |
#endif |
| if(sock==-1)return(-1); |
if (sock == -1) |
| |
return -1; |
| |
|
| |
sin.sin_family = AF_INET; |
| |
sin.sin_addr.s_addr = *((unsigned int *) he->h_addr); |
| |
sin.sin_port = htons(port); |
| #if NET_CONNECTION_DEBUG |
#if NET_CONNECTION_DEBUG |
| fprintf(stderr," STATUS: Trying to connect...\n"); |
fprintf(stderr," STATUS: Trying to connect...\n"); |
| #endif |
#endif |
| if(connect(sock,(struct sockaddr*)&sin,sizeof(struct sockaddr_in))==-1){ |
if (connect(sock, (struct sockaddr *) &sin, |
| |
sizeof(struct sockaddr_in)) == -1) { |
| #if NET_CONNECTION_DEBUG |
#if NET_CONNECTION_DEBUG |
| fprintf(stderr," ERROR: Cannot connect.\n"); |
fprintf(stderr," ERROR: cannot connect\n"); |
| #endif |
#endif |
| return(-1); |
return -1; |
| } |
} |
| #if NET_CONNECTION_DEBUG |
#if NET_CONNECTION_DEBUG |
| fprintf(stderr," OK: Connection estabilished.\n"); |
fprintf(stderr," OK: connection estabilished\n"); |
| #endif |
#endif |
| return(sock); |
return sock; |
| } |
} /* }}} */ |
| |
|
| int net_connection_read(int handle,char*buffer,int size){ |
void net_connection_close(int *handle) /* {{{ */ |
| |
{ |
| |
if (*handle > 0) |
| |
close(*handle); |
| |
*handle = -1; |
| |
return; |
| |
} /* }}} */ |
| |
|
| |
int net_connection_is_open(int *handle) /* {{{ */ |
| |
{ |
| |
return *handle > 0; |
| |
} /* }}} */ |
| |
|
| |
static int __net_connection_read(int *handle, void *buffer, int size, int mode) /* {{{ */ |
| |
{ |
| |
register int ret, to_read; |
| struct timeval tv; |
struct timeval tv; |
| fd_set rd,act; |
fd_set read_set; |
| |
|
| |
if (! net_connection_is_open(handle)) |
| |
return 0; |
| |
|
| |
if (size <= 0) |
| |
return 0; |
| |
|
| |
for (to_read = size; to_read > 0; ) { |
| |
|
| |
if (mode == READ_BLOCKED && to_read != size) |
| |
mode = READ_NORMAL; |
| |
|
| |
FD_ZERO(&read_set); |
| |
FD_SET(*handle, &read_set); |
| |
|
| |
if (mode == READ_NORMAL) { |
| |
tv.tv_sec = 0; |
| |
tv.tv_usec = 0; |
| |
ret = select(*handle + 1, &read_set, NULL, NULL, &tv); |
| |
} else { |
| |
ret = select(*handle + 1, &read_set, NULL, NULL, NULL); |
| |
} |
| |
|
| |
if (ret <= 0) { |
| |
if (ret < 0) |
| |
net_connection_close(handle); |
| |
break; |
| |
} |
| |
|
| |
ret = read(*handle, (void *) ((char *) buffer + size - to_read), to_read); |
| |
|
| |
if (ret <= 0) { |
| |
net_connection_close(handle); |
| |
break; |
| |
} |
| |
|
| |
to_read -= ret; |
| |
} |
| |
|
| |
return size - to_read; |
| |
} /* }}} */ |
| |
|
| FD_ZERO(&rd); |
int net_connection_read(int *handle, void *buffer, int size) /* {{{ */ |
| FD_ZERO(&act); |
{ |
| FD_SET(handle,&rd); |
return __net_connection_read(handle, buffer, size, READ_NORMAL); |
| FD_SET(handle,&act); |
} /* }}} */ |
| tv.tv_sec=0; |
|
| tv.tv_usec=0; |
int net_connection_read_blocked(int *handle, void *buffer, int size) /* {{{ */ |
| |
{ |
| select(handle+1,&rd,NULL,&act,&tv); |
return __net_connection_read(handle, buffer, size, READ_BLOCKED); |
| |
} /* }}} */ |
| if(FD_ISSET(handle,&rd)){ |
|
| int i; |
int net_connection_read_full(int *handle, void *buffer, int size) /* {{{ */ |
| i=read(handle,buffer,size-1); |
{ |
| if(i<=0)return(-1); |
return __net_connection_read(handle, buffer, size, READ_FULL); |
| buffer[i]='\0'; |
} /* }}} */ |
| return(i); |
|
| |
int net_connection_gets(int *handle, char *buffer, int size) |
| |
{ |
| |
register int ret, to_read, bytes_read, linebuf_fetched = 0; |
| |
register char *str_eos, *str_eol; |
| |
|
| |
for (to_read = size - 1, bytes_read = 0, str_eos = str_eol = NULL; |
| |
net_connection_is_open(handle) |
| |
&& to_read > 0 |
| |
&& str_eos == NULL |
| |
&& str_eol == NULL; ) { |
| |
|
| |
if (linebuf_fetched) { |
| |
ret = net_connection_read(handle, |
| |
(void *) (buffer + size - to_read - 1), to_read); |
| |
if (ret == 0) |
| |
break; |
| |
} else { |
| |
ret = linebuf_fetch(*handle, |
| |
(void *) (buffer + size - to_read - 1), to_read); |
| |
linebuf_fetched = 1; |
| |
} |
| |
|
| |
to_read -= ret; |
| |
bytes_read += ret; |
| |
|
| |
str_eos = (char *) memchr((void *) buffer, '\0', bytes_read); |
| |
str_eol = (char *) memchr((void *) buffer, '\n', bytes_read); |
| } |
} |
| if(FD_ISSET(handle,&act))return(-1); |
|
| return(0); |
if (str_eos == NULL && str_eol == NULL) { |
| |
if (bytes_read == size) |
| |
buffer[bytes_read] = '\0'; |
| |
else { |
| |
linebuf_append(*handle, buffer, bytes_read); |
| |
buffer[0] = '\0'; |
| |
} |
| |
} else { |
| |
register int bytes_used; |
| |
|
| |
if (str_eos != NULL && str_eol != NULL) { |
| |
str_eos = str_eos > str_eol ? NULL : str_eos; |
| |
str_eol = str_eol > str_eos ? NULL : str_eol; |
| |
} |
| |
|
| |
if (str_eos != NULL) { |
| |
bytes_used = str_eos - buffer + 1; |
| |
linebuf_append(*handle, str_eos + 1, bytes_read - bytes_used); |
| |
} |
| |
|
| |
if (str_eol != NULL) { |
| |
bytes_used = str_eol - buffer + 1; |
| |
linebuf_append(*handle, str_eos + 1, bytes_read - bytes_used); |
| |
*(str_eol + 1) = '\0'; |
| |
} |
| |
} |
| |
|
| |
return strlen(buffer); |
| } |
} |
| |
|
| |
#if 0 |
| |
int net_connection_gets_blocked(int *handle, char *buffer, int size) |
| |
{ |
| |
return 0; |
| |
} |
| |
|
| int net_connection_gets(int handle,char*buffer,int size){ |
int net_connection_gets(int handle,char*buffer,int size){ |
| |
|
| Line 131 int net_connection_gets(int handle,char* |
|
| Line 327 int net_connection_gets(int handle,char* |
|
| |
|
| return(ret); |
return(ret); |
| } |
} |
| |
#endif |
| |
|
| |
#if defined(SELF) || defined(SELFTEST) || defined(SELF_NET_CONNECTION) |
| |
|
| |
#include <stdio.h> |
| |
|
| |
#define BUFSIZE 10 |
| |
|
| |
int main(int argc, char **argv) |
| |
{ |
| |
register int port = 25; |
| |
char *server = "localhost", buffer[BUFSIZE]; |
| |
int handle, ret; |
| |
|
| |
handle = net_connection_open(server, port); |
| |
|
| |
if (handle < 0) { |
| |
fprintf(stderr, "cannot connect to %s:%d\n", server, port); |
| |
return 1; |
| |
} |
| |
|
| |
printf("net_connection_read() test\n"); |
| |
printf("fetching first %d bytes from connection:\n", BUFSIZE - 1); |
| |
|
| |
while (net_connection_is_open(&handle) && |
| |
(ret = net_connection_read(&handle, buffer, BUFSIZE - 1)) == 0) |
| |
; |
| |
buffer[ret] = '\0'; |
| |
printf(">>> [%s] (%d characters)\n", buffer, ret); |
| |
|
| |
while (net_connection_is_open(&handle)) { |
| |
ret = net_connection_gets(&handle, buffer, BUFSIZE); |
| |
if (ret > 0) |
| |
printf("[%s] (%d characters)\n", buffer, ret); |
| |
} |
| |
|
| |
net_connection_close(&handle); |
| |
|
| |
return 0; |
| |
} |
| |
|
| |
#endif |
| |
|
| |
/* Modeline for ViM {{{ |
| |
* vim: set ts=4: |
| |
* vim600: fdm=marker fdl=0 fdc=0: |
| |
* }}} */ |
| |
|