void Sys_Net_Wait(struct SysNetData *netdata, struct SysSocket *socket, unsigned int timeout_us) { fd_set rfds; ULONG sigmask; WaitIO((struct IORequest *)netdata->timerrequest); if (SetSignal(0, 0) & (1<<netdata->timerport->mp_SigBit)) Wait(1<<netdata->timerport->mp_SigBit); FD_ZERO(&rfds); FD_SET(socket->s, &rfds); netdata->timerrequest->tr_node.io_Command = TR_ADDREQUEST; netdata->timerrequest->tr_time.tv_secs = timeout_us / 1000000; netdata->timerrequest->tr_time.tv_micro = timeout_us % 1000000; SendIO((struct IORequest *)netdata->timerrequest); sigmask = 1<<netdata->timerport->mp_SigBit; WaitSelect(socket->s + 1, &rfds, 0, 0, 0, &sigmask); AbortIO((struct IORequest *)netdata->timerrequest); }
/** * Check whether we received/can send some data from/to the content server and * when that's the case handle it appropriately */ void ClientNetworkContentSocketHandler::SendReceive() { if (this->sock == INVALID_SOCKET || this->isConnecting) return; if (this->lastActivity + IDLE_TIMEOUT < _realtime_tick) { this->Close(); return; } fd_set read_fd, write_fd; struct timeval tv; FD_ZERO(&read_fd); FD_ZERO(&write_fd); FD_SET(this->sock, &read_fd); FD_SET(this->sock, &write_fd); tv.tv_sec = tv.tv_usec = 0; // don't block at all. #if !defined(__MORPHOS__) && !defined(__AMIGA__) select(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv); #else WaitSelect(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv, NULL); #endif if (FD_ISSET(this->sock, &read_fd)) { this->Recv_Packets(); this->lastActivity = _realtime_tick; } this->writable = !!FD_ISSET(this->sock, &write_fd); this->Send_Packets(); }
static int iread( struct ftp_info *info, int skt, BOOL checkbreak ) { //struct opusftp_globals *ogp = info->fi_og; int retval = -1; fd_set rd, ex; ULONG flags; struct timeval timer = { 0, 0 }; // set network timeout for the select wait call set_timeout(info,&timer); FD_ZERO( &rd ); FD_ZERO( &ex ); FD_SET( skt,&rd ); FD_SET( skt,&ex ); flags = checkbreak ? SIGBREAKF_CTRL_D : 0; // WaitSelect returns number of ready file descriptors if // successful. Zero (0) if a timeout occurred. // (-1) upon error. if (WaitSelect( skt+1, &rd, 0L, &ex, &timer, &flags ) >= 0) { D(bug("recv - ")); // is data available from the socket? if (FD_ISSET( skt, &rd )) { // number of bytes read if successful else -1. // can be 0 for EOF retval = recv( skt, info->fi_bufiobuf, BUFIOBUFSIZE, 0 ); } #ifdef DEBUG // has the socket been closed? if (FD_ISSET( skt, &ex )) D(bug( "** iread() socket exception\n" )); #endif // whatever check if user has hit CTRL_D if (flags & SIGBREAKF_CTRL_D) { info->fi_abortsignals = 0; D(bug( "*** iread() CTRL-D SIGNAL ***\n" )); retval = -1; } } return(retval); }
void Sys_Net_Wait(struct SysNetData *netdata, struct SysSocket *socket, unsigned int timeout_us) { struct timeval tv; fd_set rfds; FD_ZERO(&rfds); FD_SET(socket->s, &rfds); tv.tv_sec = timeout_us / 1000000; tv.tv_usec = timeout_us % 1000000; WaitSelect(socket->s + 1, &rfds, 0, 0, &tv, 0); }
/** * Check whether this socket can send or receive something. * @return \c true when there is something to receive. * @note Sets #writable if more data can be sent. */ bool NetworkTCPSocketHandler::CanSendReceive() { fd_set read_fd, write_fd; struct timeval tv; FD_ZERO(&read_fd); FD_ZERO(&write_fd); FD_SET(this->sock, &read_fd); FD_SET(this->sock, &write_fd); tv.tv_sec = tv.tv_usec = 0; // don't block at all. #if !defined(__MORPHOS__) && !defined(__AMIGA__) if (select(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv) < 0) return false; #else if (WaitSelect(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv, NULL) < 0) return false; #endif this->writable = !!FD_ISSET(this->sock, &write_fd); return FD_ISSET(this->sock, &read_fd) != 0; }
/* static */ void NetworkHTTPSocketHandler::HTTPReceive() { /* No connections, just bail out. */ if (_http_connections.Length() == 0) return; fd_set read_fd; struct timeval tv; FD_ZERO(&read_fd); for (NetworkHTTPSocketHandler **iter = _http_connections.Begin(); iter < _http_connections.End(); iter++) { FD_SET((*iter)->sock, &read_fd); } tv.tv_sec = tv.tv_usec = 0; // don't block at all. #if !defined(__MORPHOS__) && !defined(__AMIGA__) int n = select(FD_SETSIZE, &read_fd, NULL, NULL, &tv); #else int n = WaitSelect(FD_SETSIZE, &read_fd, NULL, NULL, &tv, NULL); #endif if (n == -1) return; for (NetworkHTTPSocketHandler **iter = _http_connections.Begin(); iter < _http_connections.End(); /* nothing */) { NetworkHTTPSocketHandler *cur = *iter; if (FD_ISSET(cur->sock, &read_fd)) { int ret = cur->Receive(); /* First send the failure. */ if (ret < 0) cur->callback->OnFailure(); if (ret <= 0) { /* Then... the connection can be closed */ cur->CloseConnection(); _http_connections.Erase(iter); delete cur; continue; } } iter++; } }
int aros_poll(struct pollfd *fds, unsigned int nfds, int timo) { struct timeval timeout, *toptr; fd_set ifds, ofds, efds, *ip, *op; unsigned int i, maxfd = 0; int rc; // Set up the file-descriptor sets in ifds, ofds and efds. FD_ZERO(&ifds); FD_ZERO(&ofds); FD_ZERO(&efds); for (i = 0, op = ip = 0; i < nfds; ++i) { fds[i].revents = 0; if(fds[i].events & (POLLIN|POLLPRI)) { ip = &ifds; FD_SET(fds[i].fd, ip); } if(fds[i].events & POLLOUT) { op = &ofds; FD_SET(fds[i].fd, op); } FD_SET(fds[i].fd, &efds); if (fds[i].fd > maxfd) { maxfd = fds[i].fd; } } // Set up the timeval structure for the timeout parameter if(timo < 0) { toptr = 0; } else { toptr = &timeout; timeout.tv_sec = timo / 1000; timeout.tv_usec = (timo - timeout.tv_sec * 1000) * 1000; } rc = WaitSelect(maxfd + 1, ip, op, &efds, toptr, NULL); if(rc <= 0) return rc; if(rc > 0) { for (i = 0; i < nfds; ++i) { int fd = fds[i].fd; if(fds[i].events & (POLLIN|POLLPRI) && FD_ISSET(fd, &ifds)) fds[i].revents |= POLLIN; if(fds[i].events & POLLOUT && FD_ISSET(fd, &ofds)) fds[i].revents |= POLLOUT; if(FD_ISSET(fd, &efds)) // Some error was detected ... should be some way to know. fds[i].revents |= POLLHUP; } } return rc; }
// // Get a remote file, calling the update function after each block arrives // Returns the total bytes received. // fi_errno MUST be checked for errors // Returns -2 for AmigaDos errors - Use IoErr() to report/handle them // Returns -3 for FTP server errors - Use the fi_reply and fi_iobuf fields to report/handle them // Returns -1 for rare unlikely errors - Could cause DisplayBeep() etc... // now uses IOBUFSIZE // // Update callback must specify 0xffffffff for total and length if REST fails // Update callback must specify 0xffffffff for unknown total // Update callback must specify 0 for length of final call // unsigned int get( struct ftp_info *info, int (*updatefn)(void *,unsigned int,unsigned int), void *updateinfo, char *remote_path, char *local_path, BOOL restart ) { // Needed because socket library base is in our task's tc_userdata field //struct opusftp_globals *ogp = info->fi_og; unsigned int total = 0xffffffff; // Length of file unsigned int bytes = 0; // Bytes received so far APTR f; // Output file int ds; // Data socket int b; // Byte count int reply; // FTP reply fd_set rd, ex; ULONG flags; struct timeval timer = {0}; int display_bytes; int done; D(bug( "get() '%s' -> '%s'\n", remote_path, local_path )); // Valid? if (!info) return 0; // No abort/error yet info->fi_aborted = 0; info->fi_errno = 0; info->fi_ioerr = 0; *info->fi_serverr = 0; // More validity if (!remote_path || !local_path) { info->fi_errno |= FTPERR_XFER_RARERR; return 0; } // init counters etc display_bytes = done = 0; // open output file for writing if ((f = OpenBuf( (char *)local_path, restart ? MODE_OLDFILE : MODE_NEWFILE, WBUFSIZE ))) { // Resuming? So find out where to resume from if (restart) { SeekBuf( f, 0, OFFSET_END ); bytes = SeekBuf( f, 0, OFFSET_CURRENT ); } // get connected - bytes is a market flag 0/x for RETR/REST if ((ds = dataconna( info, bytes, "RETR %s", remote_path )) < 0) { // Source (server error)? if (ds == -2 || ds == -3) { info->fi_errno |= FTPERR_XFER_SRCERR; stccpy( info->fi_serverr, info->fi_iobuf, IOBUFSIZE + 1 ); } else info->fi_errno |= FTPERR_XFER_RARERR; } else { char *p; // Reset bytes if REST failed if (bytes && (info->fi_flags & FTP_NO_REST)) { if (updatefn) (*updatefn)( updateinfo, 0xffffffff, 0xffffffff ); SeekBuf( f, 0, OFFSET_BEGINNING ); bytes = 0; } // First update tells callback where we're starting from if (updatefn) (*updatefn)( updateinfo, total, bytes ); // Does the RETR reply contain the file length? if ((p = strstr( info->fi_iobuf, " bytes)" ))) if (isdigit(*--p)) { while (isdigit(*p--)) ; total = atoi(p+2); } // do the transfer FD_ZERO( &rd ); FD_ZERO( &ex ); // set network timeout for the select wait call set_timeout(info,&timer); // loop fetch tcp data and save it while (!done) { // Note: these masks must be set before every call and // are all cleared by select wait. Examine the masks // afterwards to see what was set FD_SET( ds, &rd ); FD_SET( ds, &ex ); flags = SIGBREAKF_CTRL_D; if (WaitSelect( ds + 1 , &rd, NULL, &ex, &timer, &flags ) >= 0) { // Is there some data ready for us? if (FD_ISSET( ds, &rd )) { // then get it and store it if ((b = recv( ds, info->fi_iobuf, IOBUFSIZE, 0 ))) { // save data if (WriteBuf( f, info->fi_iobuf, b ) == b) { bytes += b; // progress bar uprate display_bytes += b; if (display_bytes >= UPDATE_BYTE_LIMIT) { if (updatefn) (*updatefn)( updateinfo, total, display_bytes ); display_bytes = 0; } } // Write Error else { info->fi_errno |= FTPERR_XFER_DSTERR; info->fi_ioerr = IoErr(); info->fi_aborted = 1; ftp_abor( info ); done = TRUE; } } else done = TRUE; } // did we get a signal to abort? if (!done && (flags & SIGBREAKF_CTRL_D)) { D(bug( "*** get() CTRL-D SIGNAL ***\n" )); info->fi_abortsignals = 0; info->fi_aborted = 1; ftp_abor( info ); // NEEDED why not just close socket? done = TRUE; } // did we get an exception? Other end closed connection maybe if (FD_ISSET( ds, &ex )) { D(bug("** get() socket exception\n")); // has been aborted from remote ? done = TRUE; } } else { // some socket error -ve a 0 == timeout D(bug( "** get() WaitSelect error\n" )); done = TRUE; } } // Final progress bar redraw at 100% (if it finished) if (!info->fi_aborted && !info->fi_errno && updatefn) (*updatefn)( updateinfo, total, 0 ); //D(bug( "--> close(%ld)\n", ds )); CloseSocket( ds ); #ifdef DEBUG // if (ui) // timeit( ui, bytes ); #endif // Get reply to socket closure Can TIMEOUT reply = getreply( info ); // If transfer was aborted, read the ABOR reply (426) // (This could get the reply to RETR (226) but it don't matter) if (info->fi_aborted && reply != 421) reply = getreply( info ); // RETR successful? - Don't set error if we forced it! // (This could get the reply to ABOR (225) but it don't matter) if (reply / 100 != COMPLETE) if (!info->fi_errno) { info->fi_errno |= FTPERR_XFER_SRCERR; stccpy( info->fi_serverr, info->fi_iobuf, IOBUFSIZE + 1 ); } } CloseBuf( f ); // Delete empty files if there was an error and we created it if (info->fi_errno && bytes == 0 && !restart) DeleteFile( (char *)local_path ); } else { info->fi_errno |= FTPERR_XFER_DSTERR; info->fi_ioerr = IoErr(); } return bytes; }
unsigned int put( struct ftp_info *info, int (*updatefn)(void *,unsigned int,unsigned int), void *updateinfo, char *local_path, char *remote_path, unsigned int restart ) { //struct opusftp_globals *ogp = info->fi_og; unsigned int bytes = 0; APTR f; // Output file int ds; // Data socket int b; // Byte count fd_set wd, ex; ULONG flags = SIGBREAKF_CTRL_D; struct timeval timer = {0}; BOOL done = FALSE; int display_bytes = 0; // Valid? if (!info) return 0; // No abort/error yet info->fi_aborted = 0; info->fi_errno = 0; info->fi_ioerr = 0; *info->fi_serverr = 0; // More validity if (!remote_path || !local_path) { info->fi_errno |= FTPERR_XFER_RARERR; return 0; } if ((f = OpenBuf( (char *)local_path, MODE_OLDFILE, WBUFSIZE ))) { // Can TIMEOUT if ((ds = dataconna( info, restart, "STOR %s", remote_path )) < 0) { // Destination (server) error? if (ds == -2 || ds == -3) { info->fi_errno |= FTPERR_XFER_DSTERR; stccpy( info->fi_serverr, info->fi_iobuf, IOBUFSIZE + 1 ); } else info->fi_errno |= FTPERR_XFER_RARERR; } else { // Resuming a transfer? if (restart) { // Start at 0 if REST failed if (info->fi_flags & FTP_NO_REST) { if (updatefn) (*updatefn)( updateinfo, 0xffffffff, 0xffffffff ); bytes = restart = 0; } // Otherwise seek to restart position else { SeekBuf( f, restart, OFFSET_BEGINNING ); bytes = restart; } } // First update tells callback where we're starting from if (updatefn) (*updatefn)( updateinfo, 0xffffffff, bytes ); // Transfer FD_ZERO( &wd ); FD_ZERO( &ex ); // set network timeout for the select wait call set_timeout(info,&timer); while (!done) { // Note: these masks must be set before every call and // are all cleared by select wait. Examine the masks // afterwards to see what was set FD_SET( ds, &wd ); FD_SET( ds, &ex ); flags = SIGBREAKF_CTRL_D; if (WaitSelect(ds+1, 0L, &wd, &ex, &timer, &flags ) >= 0) { if (FD_ISSET( ds, &wd )) { if ((b = ReadBuf( f, info->fi_iobuf, IOBUFSIZE )) > 0) { send( ds, info->fi_iobuf, b, 0 ); bytes += b; if ((display_bytes += b) >= UPDATE_BYTE_LIMIT || bytes < UPDATE_BYTE_LIMIT) { if (updatefn) (*updatefn)( updateinfo, 0xffffffff, display_bytes ); display_bytes = 0; } } else { done = TRUE; if (b < 0) { info->fi_errno |= FTPERR_XFER_SRCERR; info->fi_ioerr = IoErr(); } } } if (!done && (flags & SIGBREAKF_CTRL_D)) { D(bug( "*** put() CTRL-D SIGNAL ***\n" )); info->fi_abortsignals = 0; info->fi_aborted = TRUE; done = TRUE; } if (FD_ISSET( ds, &ex )) { D(bug( "** put() socket exception\n" )); info->fi_abortsignals = 0; done = TRUE; } } else { // some socket error -ve a 0== timeout D(bug("** put() WaitSelect error\n")); done = TRUE; } } // Final progress bar redraw at 100% (if it finished) if (!info->fi_aborted && !info->fi_errno && updatefn) (*updatefn)( updateinfo, 0xffffffff, 0 ); // Close data socket //D(bug( "--> close(%ld)\n", ds )); CloseSocket( ds ); // Get reply to socket closure - Can TIMEOUT if (getreply( info ) / 100 != COMPLETE) { info->fi_errno |= FTPERR_XFER_DSTERR; stccpy( info->fi_serverr, info->fi_iobuf, IOBUFSIZE + 1 ); } } CloseBuf( f ); } else { info->fi_errno |= FTPERR_XFER_SRCERR; info->fi_ioerr = IoErr(); } return bytes; }
// // Single character get char function // Returns char for success // Returns -1 for error // Returns -2 for timeout // Returns -3 for control-D break // // checkabort_time is set either to default or special time for // getput only on dest STOR command // static int sgetc( struct ftp_info *info, int skt, int checkabort_time ) { //struct opusftp_globals *ogp = info->fi_og; int retval = -1; unsigned char c; fd_set rd, ex; ULONG flags; int n, nds; struct timeval t = {0}; // Valid? if (!info || skt < 0) { D(bug( "** sgetc invalid!\n" )); return retval; } // set network timeout for the select wait call if (checkabort_time == 2) t.tv_secs = 5; // special return soon to update progress bar else set_timeout(info,&t); t.tv_micro = 0; FD_ZERO( &rd ); FD_ZERO( &ex ); FD_SET( skt, &rd ); FD_SET( skt, &ex ); flags = checkabort_time ? SIGBREAKF_CTRL_D : 0; // WaitSelect returns number of ready file descriptors if // successful. Zero (0) if a timeout occurred. // (-1) upon error. if ((nds = WaitSelect( skt+1, &rd, 0L, &ex, &t, &flags )) >= 0) { if (nds == 0) // timeout or abort { D(bug( "** sgetc() WaitSelect timeout\n" )); retval = -2; } // abort button hit? if (flags & SIGBREAKF_CTRL_D) { info->fi_abortsignals = 0; D(bug( "*** sgetc() CTRL-D SIGNAL ***\n" )); retval = -3; } // is data ready? if (FD_ISSET( skt, &rd )) if ((n = recv( skt, &c, 1, 0 )) == 1) retval = c; #ifdef DEBUG // has the socket been closed? if (FD_ISSET( skt, &ex )) D(bug( "** sgetc() socket exception\n" )); #endif } return retval; }
int poll( struct pollfd *pfds, unsigned int nfds, int timeout ) { unsigned int i; int maxfd = -1, ret; fd_set rset,wset,xset; struct timeval timeout_tv, *tvp = NULL; if (timeout >= 0) { timeout_tv.tv_sec = (timeout / 1000); timeout_tv.tv_usec = (timeout % 1000) * 1000; tvp = &timeout_tv; } if(pfds==NULL||nfds<1) { if(pfds==NULL&&nfds<1&&timeout>=0) { ret = WaitSelect(0,NULL,NULL,NULL,tvp,NULL); __chkabort(); return(ret); } errno=EINVAL; return -1; } FD_ZERO (&rset); FD_ZERO (&wset); FD_ZERO (&xset); for (i = 0; i < nfds; i++) { pfds[i].revents = 0; if (pfds[i].events == 0) continue; if (pfds[i].fd > maxfd) maxfd = pfds[i].fd; if (pfds[i].events & POLLIN) FD_SET (pfds[i].fd, &rset); if (pfds[i].events & POLLOUT) FD_SET (pfds[i].fd, &wset); if (pfds[i].events & POLLERR) FD_SET (pfds[i].fd, &xset); } ret = WaitSelect (maxfd + 1, &rset, &wset, &xset, tvp, NULL); __chkabort ( ) ; if(ret == -1) return ret; for (i = 0; i < nfds; i++) { if (pfds[i].events == 0) continue; if (FD_ISSET (pfds[i].fd, &rset)) pfds[i].revents |= POLLIN; if (FD_ISSET (pfds[i].fd, &wset)) pfds[i].revents |= POLLOUT; if (FD_ISSET (pfds[i].fd, &xset)) pfds[i].revents |= POLLERR; } return ret; }