int main() { int64 r; if (!io_fd(0)) return 111; if (!io_fd(1)) return 111; for (;;) { if (flageof && writepos >= readpos) return 0; if (!flageof && readpos < sizeof buf) io_wantread(0); if (writepos < readpos) io_wantwrite(1); io_wait(); if (!flageof && readpos < sizeof buf) io_dontwantread(0); if (writepos < readpos) io_dontwantwrite(1); if (!flageof && readpos < sizeof buf) { r = io_tryread(0,buf + readpos,sizeof buf - readpos); if (r <= -2) return 111; /* read error other than EAGAIN */ if (r == 0) flageof = 1; if (r > 0) readpos += r; } if (writepos < readpos) { r = io_trywrite(1,buf + writepos,readpos - writepos); if (r <= -2) return 111; /* write error other than EAGAIN */ if (r > 0) { writepos += r; if (writepos == readpos) readpos = writepos = 0; /* if writepos is big, might want to left-shift buffer here */ } } } }
static void handle_accept( const int64 serversocket ) { struct http_data *h; unsigned char ip[4]; uint16 port; tai6464 t; int64 i; while( ( i = socket_accept4( serversocket, (char*)ip, &port) ) != -1 ) { /* Put fd into a non-blocking mode */ io_nonblock( i ); if( !io_fd( i ) || !( h = (struct http_data*)malloc( sizeof( struct http_data ) ) ) ) { io_close( i ); continue; } io_setcookie( i, h ); io_wantread( i ); memset( h, 0, sizeof( struct http_data ) ); memmove( h->ip, ip, sizeof( ip ) ); stats_issue_event( EVENT_ACCEPT, 1, ntohl(*(uint32_t*)ip)); /* That breaks taia encapsulation. But there is no way to take system time this often in FreeBSD and libowfat does not allow to set unix time */ taia_uint( &t, 0 ); /* Clear t */ tai_unix( &(t.sec), (g_now + OT_CLIENT_TIMEOUT) ); io_timeout( i, t ); } if( errno == EAGAIN ) io_eagain( serversocket ); }
int io_socketpair(int64* d) { int fds[2]; __winsock_init(); if (socketpair(AF_UNIX,SOCK_STREAM,0,fds)==-1) if (socketpair(AF_INET6,SOCK_STREAM,IPPROTO_TCP,fds)==-1) if (socketpair(AF_INET,SOCK_STREAM,IPPROTO_TCP,fds)==-1) return 0; if (io_fd(fds[1]) && io_fd(fds[0])) { d[0]=fds[0]; d[1]=fds[1]; return 1; } io_close(fds[1]); io_close(fds[0]); return 0; }
static void handle_reconnects( void ) { int i; for( i=0; i<g_connection_count; ++i ) if( PROXYPEER_NEEDSCONNECT( g_connections[i].state ) ) { int64 newfd = socket_tcp6( ); fprintf( stderr, "(Re)connecting to peer..." ); if( newfd < 0 ) continue; /* No socket for you */ io_fd(newfd); if( socket_bind6_reuse(newfd,g_serverip,g_serverport,0) ) { io_close( newfd ); continue; } if( socket_connect6(newfd,g_connections[i].ip,g_connections[i].port,0) == -1 && errno != EINPROGRESS && errno != EWOULDBLOCK ) { close(newfd); continue; } io_wantwrite(newfd); /* So we will be informed when it is connected */ io_setcookie(newfd,g_connections+i); /* Prepare connection info block */ reset_info_block( g_connections+i ); g_connections[i].fd = newfd; PROXYPEER_SETCONNECTING( g_connections[i].state ); } g_connection_reconn = time(NULL) + 30; }
int io_pipe(int64* d) { #ifdef __MINGW32__ HANDLE fds[2]; if (CreatePipe(fds,fds+1,0,0)==0) return 0; #else int fds[2]; if (pipe(fds)==-1) return 0; #endif if (io_fd(fds[1]) && io_fd(fds[0])) { d[0]=fds[0]; d[1]=fds[1]; return 1; } io_close(fds[1]); io_close(fds[0]); return 0; }
static void ot_try_bind( char ip[4], uint16 port, int is_tcp ) { int64 s = is_tcp ? socket_tcp4( ) : socket_udp4(); if( socket_bind4_reuse( s, ip, port ) == -1 ) panic( "socket_bind4_reuse" ); if( is_tcp && ( socket_listen( s, SOMAXCONN) == -1 ) ) panic( "socket_listen" ); if( !io_fd( s ) ) panic( "io_fd" ); io_setcookie( s, is_tcp ? FLAG_TCP : FLAG_UDP ); io_wantread( s ); }
static int64_t ot_try_bind( ot_ip6 ip, uint16_t port ) { int64 sock = socket_tcp6( ); if( socket_bind6_reuse( sock, ip, port, 0 ) == -1 ) panic( "socket_bind6_reuse" ); if( socket_listen( sock, SOMAXCONN) == -1 ) panic( "socket_listen" ); if( !io_fd( sock ) ) panic( "io_fd" ); io_setcookie( sock, (void*)FLAG_SERVERSOCKET ); io_wantread( sock ); return sock; }
int iob_addfile_close(io_batch* b,int64 fd,uint64 off,uint64 n) { iob_entry* e; if (n==0) { io_close(fd); return 1; } io_fd(fd); e=array_allocate(&b->b,sizeof(iob_entry), array_length(&b->b,sizeof(iob_entry))); if (!e) return 0; e->type=FROMFILE; e->fd=fd; e->buf=0; e->n=n; e->offset=off; e->cleanup=cleanup; b->bytesleft+=n; ++b->files; return 1; }
/* Handle incoming connection requests, check against whitelist */ static void handle_accept( int64 serversocket ) { int64 newfd; ot_ip6 ip; uint16 port; while( ( newfd = socket_accept6( serversocket, ip, &port, NULL ) ) != -1 ) { /* XXX some access control */ /* Put fd into a non-blocking mode */ io_nonblock( newfd ); if( !io_fd( newfd ) ) io_close( newfd ); else { /* Find a new home for our incoming connection */ int i; for( i=0; i<MAX_PEERS; ++i ) if( g_connections[i].state == FLAG_DISCONNECTED ) break; if( i == MAX_PEERS ) { fprintf( stderr, "No room for incoming connection." ); close( newfd ); continue; } /* Prepare connection info block */ reset_info_block( g_connections+i ); PROXYPEER_SETCONNECTING( g_connections[i].state ); g_connections[i].port = port; g_connections[i].fd = newfd; io_setcookie( newfd, g_connections + i ); /* We expect the connecting side to begin with its tracker_id */ io_wantread( newfd ); } } return; }
int main() { int64 pfd[2]; char buf[20480]; unsigned int i; if (!io_pipe(pfd)) return 111; io_nonblock(pfd[1]); if (!io_fd(pfd[1])) return 111; switch (fork()) { case -1: return 111; case 0: /* child */ io_close(pfd[1]); sleep(1); for (;;) { switch (io_waitread(pfd[0],buf,sizeof buf)) { case -1: buffer_putsflush(buffer_2,"io_waitread returned -1!\n"); return 111; case -3: buffer_puts(buffer_2,"io_waitread: "); buffer_puterror(buffer_2); buffer_putnlflush(buffer_2); return 111; case 0: io_close(pfd[0]); return 0; } } } io_close(pfd[0]); for (i=0; i<sizeof(buf); ++i) buf[i]="abcdefghihjklmnopqrstuvwxyz"[i%26]; for (i=0; i<1000; ++i) { int64 r; if ((r=io_waitwrite(pfd[1],buf,sizeof buf))!=sizeof buf) { buffer_puts(buffer_2,"io_waitwrite returned "); buffer_putlonglong(buffer_2,r); buffer_putnlflush(buffer_2); } } return 0; }
int main(int argc,char* argv[]) { char server[1024]; int* fds; int* avail; int* keepleft; long long* expected; unsigned long n=10000; /* requests */ unsigned long c=10; /* concurrency */ unsigned long t=0; /* time limit in seconds */ unsigned long k=0; /* keep-alive */ unsigned long K=1; /* keep-alive counter */ int report=0; unsigned long long errors=0; unsigned long long bytes=0; int v=0; unsigned long i,done; uint16 port=80; uint32 scope_id=0; stralloc ips={0}; char* request,* krequest; unsigned long rlen, krlen; tai6464 first,now,next,last; enum { SAME, REPLAY } mode; char* hostname; server[0]=0; errmsg_iam("bench"); #ifndef __MINGW32__ signal(SIGPIPE,SIG_IGN); #endif for (;;) { int i; int ch=getopt(argc,argv,"n:c:t:kvK:C:r"); if (ch==-1) break; switch (ch) { case 'r': report=1; break; case 'n': i=scan_ulong(optarg,&n); if (i==0) die(1,"could not parse -n argument \"",optarg,"\".\n"); break; case 'c': i=scan_ulong(optarg,&c); if (i==0) die(1,"could not parse -c argument \"",optarg,"\".\n"); break; case 't': i=scan_ulong(optarg,&t); if (i==0) die(1,"could not parse -t argument \"",optarg,"\".\n"); break; case 'k': k=1; break; case 'K': i=scan_ulong(optarg,&K); break; case 'v': v=1; break; case 'C': cookiefile(optarg); break; case '?': break; default: usage(); } } if (n<1 || c<1 || !argv[optind]) usage(); if (argv[optind][0]=='@') { mode=REPLAY; char* host; n=(unsigned long)-1; host=argv[optind]+1; { int tmp; tmp=str_chr(host,'/'); if (host[tmp]) { host[tmp]=0; if (!scan_ushort(host+tmp+1,&port)) usage(); } tmp=str_chr(host,'%'); if (host[tmp]) { host[tmp]=0; scope_id=socket_getifidx(host+tmp+1); if (scope_id==0) carp("warning: network interface \"",host+tmp+1,"\" not found."); } } { stralloc a={0}; stralloc_copys(&a,host); if (dns_ip6(&ips,&a)==-1) die(1,"could not find IP for \"",host,"\"!"); } hostname=host; request=krequest=0; rlen=krlen=0; } else { char* host=argv[optind]; int colon; int slash; char* c; mode=SAME; if (byte_equal(host,7,"http://")) host+=7; colon=str_chr(host,':'); slash=str_chr(host,'/'); if (host[0]=='[') { /* ipv6 IP notation */ int tmp; ++host; --colon; --slash; tmp=str_chr(host,']'); if (host[tmp]==']') host[tmp]=0; if (host[tmp+1]==':') colon=tmp+1; if (colon<tmp+1) colon=tmp+1+str_len(host+tmp+1); } if (colon<slash) { host[colon]=0; c=host+colon+1; if (c[scan_ushort(c,&port)]!='/') usage(); *c=0; } host[colon]=0; c=host+slash; *c=0; { char* tmp=alloca(str_len(host)+1); tmp[fmt_str(tmp,host)]=0; host=tmp; } *c='/'; { int tmp=str_chr(host,'%'); if (host[tmp]) { host[tmp]=0; scope_id=socket_getifidx(host+tmp+1); if (scope_id==0) carp("warning: network interface \"",host+tmp+1,"\" not found."); } } { stralloc a={0}; stralloc_copys(&a,host); if (dns_ip6(&ips,&a)==-1) die(1,"could not find IP for \"",host,"\"!"); } request=alloca(1300+str_len(host)+3*str_len(c)); krequest=alloca(1300+str_len(host)+3*str_len(c)); { int i,j; i=fmt_str(request,"GET "); i+=fmt_urlencoded(request+i,c,str_len(c)); i+=fmt_str(request+i," HTTP/1.0\r\nHost: "); i+=fmt_str(request+i,host); i+=fmt_str(request+i,":"); i+=fmt_ulong(request+i,port); i+=fmt_str(request+i,"\r\nUser-Agent: bench/1.0\r\nConnection: "); j=i; i+=fmt_str(request+i,"close\r\n\r\n"); rlen=i; request[rlen]=0; byte_copy(krequest,rlen,request); i=j+fmt_str(krequest+j,"keep-alive\r\n\r\n"); krlen=i; krequest[krlen]=0; } hostname=host; } fds=alloca(c*sizeof(*fds)); avail=alloca(c*sizeof(*avail)); expected=alloca(c*sizeof(*expected)); keepleft=alloca(c*sizeof(*keepleft)); last.sec.x=23; if (!k) K=1; for (i=0; i<c; ++i) { fds[i]=-1; avail[i]=1; keepleft[i]=K; } taia_now(&first); for (done=0; done<n; ) { if (t) { /* calculate timeout */ taia_now(&now); if (now.sec.x != last.sec.x) { byte_copy(&last,sizeof(now),&now); byte_copy(&next,sizeof(now),&now); next.sec.x += t; while ((i=io_timeouted())!=-1) { unsigned long j; char numbuf[FMT_ULONG]; numbuf[fmt_ulong(numbuf,i)]=0; carp("timeout on fd ",numbuf,"!"); j=(unsigned long)io_getcookie(i); io_close(i); avail[j]=1; fds[j]=-1; } } } /* first, fill available connections */ for (i=0; i<c; ++i) if (avail[i]==1 && fds[i]==-1) { fds[i]=make_connection(ips.s,port,scope_id,-1); if (fds[i]==-1) diesys(1,"socket/connect"); avail[i]=2; if (io_fd(fds[i])==0) diesys(1,"io_fd"); io_setcookie(fds[i],(void*)i); // io_wantread(fds[i]); io_wantwrite(fds[i]); } if (t) io_waituntil(next); else io_wait(); /* second, see if we can write on a connection */ while ((i=io_canwrite())!=-1) { int j; j=(unsigned long)io_getcookie(i); if (avail[j]==2) { if (make_connection(ips.s,port,scope_id,i)==-1) { ++errors; if (v) write(1,"!",1); io_close(i); avail[j]=1; fds[j]=-1; continue; } } { char* towrite; int writelen; if (mode==REPLAY) { static long lines; char line[1024]; char req[2048]; int len; int i; char* c; char* host; int hlen; if ((len=buffer_getline(buffer_0,line,sizeof(line)))) { ++lines; if (line[len]!='\n') die(0,"line too long: ",line); line[len]=0; c=line; if (str_start(line,"http://")) c+=7; if (c[0]=='/') { host=hostname; hlen=strlen(hostname); } else { host=c; c+=(hlen=str_chr(c,'/')); } if (!*c) c="/"; i=fmt_str(req,"GET "); i+=fmt_urlencoded(req+i,c,str_len(c)); i+=fmt_str(req+i," HTTP/1.0\r\nHost: "); byte_copy(req+i,hlen,host); i+=hlen; i+=fmt_str(req+i,":"); i+=fmt_ulong(req+i,port); if (cookies) { int j; i+=fmt_str(req+i,"\r\n"); j=nextcookie(req+i,sizeof(req)-i-100); if (j!=-1) i+=j; else i-=2; } i+=fmt_str(req+i,"\r\nUser-Agent: bench/1.0\r\nConnection: "); i+=fmt_str(req+i,keepleft[j]>1?"keep-alive\r\n\r\n":"close\r\n\r\n"); req[i]=0; towrite=req; writelen=i; } else { n=done; break; } } else { if (keepleft[j]>1) { towrite=krequest; writelen=krlen; } else { towrite=request; writelen=rlen; } if (cookies) { int i=writelen-2; int j=nextcookie(towrite+i,900); if (j!=-1) i+=j; i+=fmt_str(towrite+i,"\r\n\r\n"); writelen=i; } } if (io_trywrite(i,towrite,writelen)!=writelen) { ++errors; if (v) write(1,"-",1); io_close(i); avail[j]=1; fds[j]=-1; continue; } } io_dontwantwrite(i); io_wantread(i); expected[j]=-1; if (v) write(1,"+",1); } /* third, see if we got served */ while ((i=io_canread())!=-1) { char buf[8193]; int l,j; buf[8192]=0; j=(unsigned long)io_getcookie(i); if ((l=io_tryread(i,buf,sizeof(buf)-1))<=0) { if (l==0) { /* EOF. Mhh. */ if (expected[j]>0) { ++errors; if (v) write(1,"-",1); /* so whine a little */ } if (expected[j]==-2) ++done; io_close(i); avail[j]=1; fds[j]=-1; } else if (l==-3) { ++errors; if (v) write(1,"!",1); // carpsys("read"); } } else { bytes+=l; if (v) write(1,".",1); /* read something */ if (expected[j]==-1) { /* expecting header */ int k; /* OK, so this is a very simplistic header parser. No * buffering. At all. We expect the Content-Length header to * come in one piece. */ if (l>10 && !memcmp(buf,"HTTP/1.",7)) { if (buf[9]>='0' && buf[9]<='9') r[buf[9]-'0']++; else { write(1,buf,15); write(1,"\n",1); } } expected[j]=-2; if (!done) { for (k=0; k<l; ++k) if (str_start(buf+k,"\nServer: ")) { char* tmp=buf+(k+=9); for (; k<l; ++k) if (buf[k]=='\r') break; k=buf+k-tmp; if (k>sizeof(server)-1) k=sizeof(server)-1; byte_copy(server,k,tmp); server[k]=0; break; } } for (k=0; k<l; ++k) { if (str_start(buf+k,"\nContent-Length: ")) { k+=17; if (buf[k+scan_ulonglong(buf+k,(unsigned long long*)expected+j)] != '\r') die(1,"parse error in HTTP header!"); } else if (str_start(buf+k,"\r\n\r\n")) break; } if (expected[j]>0) { if (l-(k+4)>expected[j]) expected[j]=0; else expected[j]-=l-(k+4); } } else if (expected[j]==-2) { /* no content-length header, eat everything until EOF */ } else { if (l>expected[j]) { carp("got more than expected!"); expected[j]=0; } else expected[j]-=l; } if (expected[j]==0) { ++done; /* one down! */ avail[j]=1; // printf("fd %d: keepleft[%d]=%d\n",i,j,keepleft[j]); if (keepleft[j]>1) { --keepleft[j]; io_dontwantread(i); io_wantwrite(i); expected[j]=0; } else { keepleft[j]=K; io_close(i); fds[j]=-1; } } } } } taia_now(&now); taia_sub(&now,&now,&first); { char a[FMT_ULONG]; char b[FMT_ULONG]; char C[FMT_ULONG]; char d[FMT_ULONG]; char e[FMT_ULONG]; char f[FMT_ULONG]; char g[FMT_ULONG]; char h[FMT_ULONG]; char i[FMT_ULONG]; char j[FMT_ULONG]; unsigned long long l; a[fmt_ulong(a,now.sec.x)]=0; b[fmt_ulong0(b,(now.nano%1000000000)/100000,4)]=0; C[fmt_ulong(C,done)]=0; d[fmt_ulonglong(d,errors)]=0; e[fmt_ulonglong(e,bytes)]=0; /* let's say bytes = 10 MB, time = 1.2 sec. * then we want 10*1024*1024/1.2 == 8 MB/sec */ l = (now.sec.x * 1024) + now.nano/976562; if (l) { int i; l=bytes/l; if (report) i=fmt_ulong(f,l); else { i=fmt_humank(f,l*1024); i+=fmt_str(f+i,"iB/sec"); } f[i]=0; } else strcpy(f,"n/a"); l = (now.sec.x * 1000) + now.nano/1000000; l = l ? (done*10000) / l : 0; g[fmt_ulong(g,l/10)]=0; h[fmt_ulong(h,c)]=0; i[fmt_ulong(i,K)]=0; j[fmt_ulong(j,kaputt)]=0; if (server[0]) msg("Server: ",server); if (report) { errmsg_iam(0); msg("req\terr\tconcur\tkeep\tkbytes\tsec\ttput\tr/s\treset"); msg(C,"\t",d,"\t",h,"\t",i,"\t",e,"\t",a,".",b,"\t",f,"\t",g,"\t",j); } else { msg(C," requests, ",d," errors."); msg(e," bytes in ",a,".",b," seconds."); msg("Throughput: ",f); msg("Requests per second: ",g); msg("Connection refused/reset by peer: ",j); } { int i; for (i=0; i<9; ++i) { a[fmt_ulong(a,r[i])]=0; b[0]=i+'0'; b[1]=0; msg(b,"xx: ",a); } } } return 0; }
int main(int argc, char* argv[]) { int s = socket_tcp6(); uint32 scope_id; char ip[16]; uint16 port; char hisip[16]; uint16 hisport; uint32 hisscope_id; static char seed[128]; static stralloc fqdn; static stralloc out; if(argc != 4) { usage: buffer_putsflush(buffer_2, "usage: proxy myip myport hisip hisport\n" "\n" "e.g.: proxy 0 119 news.fu-berlin.de 119\n"); return 0; } if(argv[1][scan_ip6if(argv[1], ip, &scope_id)]) { if(str_equal(argv[1], "0")) { byte_zero(ip, 16); scope_id = 0; } else goto usage; } if(argv[2][scan_ushort(argv[2], &port)]) goto usage; if(argv[3][scan_ip6if(argv[3], hisip, &hisscope_id)]) { dns_random_init(seed); if(!stralloc_copys(&fqdn, argv[3])) goto nomem; if(dns_ip4(&out, &fqdn) == -1) { buffer_puts(buffer_2, "unable to find IP address for "); buffer_puts(buffer_2, argv[3]); buffer_puts(buffer_2, ": "); buffer_puterror(buffer_2); buffer_putnlflush(buffer_2); return 111; } } else if(!stralloc_catb(&out, hisip, 16)) { nomem: buffer_putsflush(buffer_2, "out of memory\n"); return 111; } if(argv[4][scan_ushort(argv[4], &hisport)]) goto usage; if(socket_bind6_reuse(s, ip, port, scope_id) == -1) { buffer_puts(buffer_2, "socket_bind6_reuse: "); buffer_puterror(buffer_2); buffer_putnlflush(buffer_2); return 111; } if(socket_listen(s, 16) == -1) { buffer_puts(buffer_2, "socket_listen: "); buffer_puterror(buffer_2); buffer_putnlflush(buffer_2); return 111; } if(!io_fd(s)) { buffer_puts(buffer_2, "io_fd: "); buffer_puterror(buffer_2); buffer_putnlflush(buffer_2); return 111; } io_wantread(s); for(;;) { int64 i; io_wait(); while((i = io_canread()) != -1) { if(i == s) { /* the read event is on the server socket */ /* that means it's an incoming connection */ int n; while((n = socket_accept6(s, ip, &port, &scope_id)) != -1) { int x = socket_tcp6(); if(x == -1) { buffer_puts(buffer_2, "socket_tcp6 failed: "); fail: buffer_puterror(buffer_2); buffer_putnlflush(buffer_2); io_close(n); } else { struct state* s = malloc(sizeof(struct state)); if(!s) goto closefail; s->a = n; s->b = x; s->connected = 0; s->done = s->todo = 0; s->dir = UNDECIDED; io_nonblock(x); socket_connect6(x, out.s, hisport, hisscope_id); if(!io_fd(x) || !io_fd(n)) { buffer_puts(buffer_2, "io_fd failed: "); closefail: free(s); io_close(x); goto fail; } io_setcookie(x, s); io_setcookie(n, s); io_wantwrite(x); } } if(errno != EAGAIN) { buffer_puts(buffer_2, "socket_accept6 failed: "); buffer_puterror(buffer_2); buffer_putnlflush(buffer_2); } } else { /* read event on an established connection */ struct state* s = io_getcookie(i); int l = io_tryread(i, s->buf, sizeof(s->buf)); if(l == -1) { buffer_puts(buffer_2, "io_tryread("); buffer_putulong(buffer_2, i); buffer_puts(buffer_2, "): "); buffer_puterror(buffer_2); buffer_putnlflush(buffer_2); io_close(s->a); io_close(s->b); } else if(l == 0) { buffer_puts(buffer_2, "eof on fd #"); buffer_putulong(buffer_2, i); buffer_putnlflush(buffer_2); io_close(i); } else { int r; switch(r = io_trywrite(i, s->buf, l)) { case -1: buffer_puts(buffer_2, "io_tryread("); buffer_putulong(buffer_2, i); buffer_puts(buffer_2, "): "); buffer_puterror(buffer_2); buffer_putnlflush(buffer_2); io_close(i); break; case 0: buffer_puts(buffer_2, "write eof on fd #"); buffer_putulong(buffer_2, i); buffer_putnlflush(buffer_2); io_close(i); default: if(r != l) { buffer_puts(buffer_2, "short write on fd #"); buffer_putulong(buffer_2, i); buffer_puts(buffer_2, ": wrote "); buffer_putulong(buffer_2, r); buffer_puts(buffer_2, ", wanted to write "); buffer_putulong(buffer_2, l); buffer_putsflush(buffer_2, ").\n"); } } } } } } return 0; }
int socket_accept4(int s,char *ip,uint16 *port) { struct sockaddr_in si; socklen_t len = sizeof si; int fd; #ifdef __MINGW32__ io_entry* e=array_get(&io_fds,sizeof(io_entry),s); if (e && e->inuse) { int sa2len; fd=-1; if (e->acceptqueued==1) { errno=EAGAIN; return -1; } if (e->acceptqueued==2) { incoming: /* incoming! */ { struct sockaddr* x,* y; GetAcceptExSockaddrs(e->inbuf,0,200,200,&x,&sa2len,&y,&len); if (len>sizeof(si)) len=sizeof(si); memcpy(&si,y,len); } fd=e->next_accept; e->next_accept=0; if (e->nonblock) { if (io_fd(fd)) { io_entry* f=array_get(&io_fds,sizeof(io_entry),fd); if (f) { f->nonblock=1; /* printf("setting fd %lu to non-blocking\n",(int)fd);*/ } } } } /* no accept queued, queue one now. */ if (e->next_accept==0) { e->next_accept=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if (e==-1) return winsock2errno(-1); } if (AcceptEx(s,e->next_accept,e->inbuf,0,200,200,&e->errorcode,&e->or)) goto incoming; if (WSAGetLastError() != ERROR_IO_PENDING) return winsock2errno(-1); e->acceptqueued=1; if (fd==-1) { errno=EAGAIN; return fd; } } else { #endif if ((fd=accept(s,(void*) &si,&len))==-1) return winsock2errno(-1); #ifdef __MINGW32__ } #endif if (ip) *(uint32*)ip = *(uint32*)&si.sin_addr; if (port) uint16_unpack_big((char *) &si.sin_port,port); return fd; }