Пример #1
0
int main(void)
{
   int nbytes=0, j=0, nwrite, ntimes = 1, success=0;
   char *ptr;

   if(set_nonblock_flag(STDOUT_FILENO, 1) < 0)     /* 設定無阻塞I/O */
      err_exit("set nonblock flag failed ");   
   while (nbytes+sizeof(fmt) < B_SIZE) {
      sprintf(&buf[nbytes],fmt,j++);
      nbytes += sizeof(fmt);
   }

   /* 將buf中的資料寫至標准輸出,直到全部寫出 */
   for(ptr=buf; nbytes >0; ntimes++){
      errno = 0;
      nwrite = write(STDOUT_FILENO, ptr, nbytes);
      if(nwrite < 0){
         fprintf(stderr,"\n%d  nwrite=%d, error=%d ",ntimes,nwrite,errno);
         perror("");
      } else {
         fprintf(stderr,"\n%d  nwrite=%d, error=%d ",ntimes,nwrite,errno);
         ptr += nwrite;
         success++;
         nbytes -= nwrite;
      }
   }
   printf("success=%d\n",success);
   exit(0);
}
Пример #2
0
void *
serve_client (void *data)
{
  struct thread_data *thread_data = data;
  int client_sock = thread_data->client_sock;
  int server_sock;
  FILE *protocol = thread_data->protocol_file;
  FILE *client;
  FILE *server;
  int err;

  client = NULL;
  server = NULL;

  /* Connect to server.  */
  err = connect_to_socket (opt.server_spec, &server_sock);
  if (err)
    goto out;

  /* Set IO mode to nonblicking.  */
  err = set_nonblock_flag (server_sock, 1);
  if (err)
    goto out;

  client = fdopen (client_sock, "r+");
  if (! client)
    {
      err = errno;
      goto out;
    }

  server = fdopen (server_sock, "r+");
  if (! server)
    {
      err = errno;
      goto out;
    }

  err = io_loop (client, server, protocol);

 out:

  if (client)
    fclose (client);
  else
    close (client_sock);

  if (server)
    fclose (server);
  else
    close (server_sock);

  free (data);

  return NULL;
}
Пример #3
0
/** read a line on a Socket_t using timeout and retries values as set in object.
 * \ingroup Socket
 * Target Socket_t must have been fully initialised by tb_Connect or tb_initServer. Read result is appended in 'msg' String_t.  
 *
 * @return number of read bytes, or -1 if error
 * Internally read is buffered for best performances. The first line found in the buffer is appended to Msg String_t. The remaining buffered data (if any) will be used on next tb_readSockLine or tb_readSock.
 *
 * \remarks ERROR:
 * in case of error tb_errno will be set to :
 * - TB_ERR_INVALID_OBJECT : So not a TB_SOCKET
 * - TB_ERR_BAD : msg is not a TB_STRING
 * 
 * @see tb_Socket, tb_writeSock, tb_writeSockBin, tb_readSockLine
*/
int tb_readSockLine(Socket_t S, String_t Msg) {
  fd_set set ;
  struct timeval tps ;
  int rc, retval;
	sock_members_t So;
	char buff[MAX_BUFFER];
	no_error;

	if(! TB_VALID(S,   TB_SOCKET)) {
		set_tb_errno(TB_ERR_INVALID_TB_OBJECT);
		return TB_ERR;
	}
	if(! TB_VALID(Msg, TB_STRING)) {
		set_tb_errno(TB_ERR_BAD);
		return TB_ERR;
	}

	So = XSock(S);

	if( So->buffer == NULL ) {
		So->buffer = tb_String(NULL);
	} else {
		if( tb_getSize(So->buffer) > 0 ) {
			char *s;
			if(( s = strchr(S2sz(So->buffer), '\n')) != NULL) {
				int len;

				len = 1+ (s - S2sz(So->buffer));
				tb_StrnAdd(Msg, len, -1, "%s", S2sz(So->buffer));
				tb_StrDel(So->buffer, 0, len);
				return len;
			}
		}
	}

  FD_ZERO(&set);
  FD_SET(So->sock, &set);
  tb_getSockTO(S, &(tps.tv_sec), &(tps.tv_usec));
 
	restart_r_select:
  rc = select(So->sock+1, &set, NULL, NULL, &tps);
  switch (rc)
    {
    case -1:
			if( errno == EINTR ) goto restart_r_select;
      tb_error("tb_readSockLine[%d]: select failed (%s)\n", 
							 So->sock, strerror(errno)); 
      // invalid fd ==> we're disconnected
      if( errno == EBADF ) So->status = TB_DISCONNECTED;
			set_tb_errno(TB_ERR_DISCONNECTED);
      retval = TB_ERR;
      break; 
    case 0:
      /* Time out */
      tb_notice("tb_readSockLine[%d]: select timed out\n", So->sock); 
      So->status = TB_TIMEDOUT;
      retval = TB_ERR;
      break ;
    default:
		restart_r_read:
#ifdef WITH_SSL
			if( So->ssl ) {
				rc = SSL_read(XSsl(S)->cx, buff, MAX_BUFFER-1);
				switch (SSL_get_error(XSsl(S)->cx,rc)) {
				case SSL_ERROR_NONE:
					buff[rc] = 0;
					tb_StrAdd(Msg, -1, "%s", buff);
					goto cutline;
				case SSL_ERROR_SYSCALL:
					if( errno ) {
						tb_error("tb_readSock[%d(SSL)]: read error (%s)\n",
										 So->sock, strerror(errno));
					}
					/* fall through */
				case SSL_ERROR_WANT_WRITE:
				case SSL_ERROR_WANT_READ:
				case SSL_ERROR_WANT_X509_LOOKUP:
				case SSL_ERROR_ZERO_RETURN:
				case SSL_ERROR_SSL:
					ERR_print_errors_fp(stderr);
					return TB_ERR;
				}
			} else {
				set_nonblock_flag(So->sock, 1);
				rc = read(So->sock, buff, MAX_BUFFER-1);
				set_nonblock_flag(So->sock, 0);
			}
#else
			set_nonblock_flag(So->sock, 1);
			rc = read(So->sock, buff, MAX_BUFFER-1);
			set_nonblock_flag(So->sock, 0);
#endif
#ifdef WITH_SSL
    cutline:
#endif // WITH_SSL
      switch( rc ) {
      case -1:
				if( errno == EINTR|| errno == EWOULDBLOCK ) goto restart_r_read;
				if( errno != EWOULDBLOCK ) {
					tb_error("tb_readSockLine[%d]: read error (%s)\n", So->sock, strerror(errno));
					retval = TB_ERR;
					So->status = TB_DISCONNECTED;
					break;
				}
      case 0:  // eof
				tb_notice("tb_readSockLine[%d]: eof reached\n", So->sock);
				*buff = 0;
				tb_StrAdd(Msg, -1, "%S", So->buffer);
				retval = TB_ERR;
				tb_Clear(So->buffer);
				break;
      default:
				buff[rc] = 0; 
				tb_StrAdd(So->buffer, -1, "%s", buff);
				{
					char *s = strchr(S2sz(So->buffer), '\n');
					if( s ) {
						int len;
						len = 1+(s - S2sz(So->buffer)); 
						tb_StrnAdd(Msg, len, -1, "%s", S2sz(So->buffer));
						tb_StrDel(So->buffer, 0, len);
						retval = len;
					} else {
						goto restart_r_select;
					}
				}
				break;
      }
      break;
    }
  return retval;
}
Пример #4
0
/** write binary on a Socket_t using timeout and retries values as set in object.
 * \ingroup Socket
 * Target Socket_t must have been fully initialised by tb_Connect or tb_initServer. 
 *
 * @return number of written bytes, or -1 if error
 *
 * see test/srv_test.c , test/socket_test.c in build tree
 *
 * \remarks ERROR:
 * in case of error tb_errno will be set to :
 * - TB_ERR_INVALID_OBJECT : So not a TB_SOCKET
 * - TB_ERR_BAD : msg is not a TB_STRING
 * 
 * @see tb_Socket, tb_writeSock, , tb_writeSockBin, tb_readSockLine
 * \todo fixme: use a pointer and a counter to remaining bytes to write for icomplete writes ...
 */
int tb_writeSockBin(Socket_t S, Raw_t raw) {
  fd_set set ;
  struct timeval tps ;
  int len, rc, remaining, retval = 0;
	char *msg;
	sock_members_t So;

	if(!TB_VALID(raw, TB_RAW)) {
		set_tb_errno(TB_ERR_BAD);
		return TB_KO;
	}
	
	if(!TB_VALID(S, TB_SOCKET)) {
		set_tb_errno(TB_ERR_INVALID_TB_OBJECT);
		return TB_ERR;
	}

	So = XSock(S);

	if(tb_getSockStatus(S) <= TB_DISCONNECTED) {
		return TB_ERR;
	}

  FD_ZERO(&set);
  FD_SET(So->sock,&set);

	msg = Raw_getData(raw);
	remaining = tb_getSize(raw);

 restart_w_select:
  tb_getSockTO(S, &tps.tv_sec, &tps.tv_usec);

  rc = select(FD_SETSIZE, NULL, &set, NULL, &tps);
  switch(rc)
    {
    case -1: 
			if( errno == EINTR ) goto restart_w_select;
      tb_error("tb_writeSock[%d]: select failed (%s)\n", So->sock, strerror(errno)); 
      // invalid fd ==> we're disconnected
      if( errno == EBADF    ||
					errno == ENOTSOCK ||
					errno == ENOTCONN ||
					errno == EPIPE ) So->status = TB_DISCONNECTED;
      retval = TB_ERR;
      break ;
    case 0:
      /* Time out */
      tb_notice("tb_writeSock[%d]: select timed out\n", So->sock); 
      So->status = TB_TIMEDOUT;
      retval = TB_KO;
      break ;
    default:
			if( ! FD_ISSET(So->sock, &set)) {
				tb_error("tb_readSock[%d]: select rc=%d but fd is not ready\n", 
								 So->sock, rc); 
				retval = TB_KO;
				break ;
			}

		restart_w_write:
#ifdef WITH_SSL
			if( So->ssl ) {
				rc=SSL_write(XSsl(S)->cx,msg , remaining);
				switch (SSL_get_error(XSsl(S)->cx,rc)) { 
				case SSL_ERROR_NONE:
					return rc;
				case SSL_ERROR_SYSCALL:
					if ((rc != 0) && errno ) {
						tb_error("tb_writeSock[%d(SSL)]: write error (%s)\n", 
										 So->sock, strerror(errno));
					}
					/* fall through */
				case SSL_ERROR_WANT_WRITE:
				case SSL_ERROR_WANT_READ:
				case SSL_ERROR_WANT_X509_LOOKUP:
				case SSL_ERROR_ZERO_RETURN:
				case SSL_ERROR_SSL:
				default:
					ERR_print_errors_fp(stderr);
					return TB_ERR;
				}
			} else {
				set_nonblock_flag(So->sock, 1);
				rc = write(So->sock, msg, len = remaining);
				set_nonblock_flag(So->sock, 0);
			}
#else
			set_nonblock_flag(So->sock, 1);
			rc = write(So->sock, msg, len = remaining);
			set_nonblock_flag(So->sock, 0);
#endif
      switch( rc ) {
      case -1:
				if( errno == EINTR ) goto restart_w_write;
				tb_error("tb_writeSock[%d]: write error (%s)\n", So->sock, strerror(errno));
				So->status = TB_DISCONNECTED;
				retval = TB_ERR;
				break;
      default:
				retval += rc;
				if( rc != remaining ) {
					tb_error("tb_writeSock[%d]: incomplet write (%d/%d)\n", So->sock, rc, len); 
					msg       += rc;
					remaining -= rc;
					goto restart_w_select;
				}
				break ;
      }
      break ;
    }

  return retval;
}
Пример #5
0
/** read on a Socket_t using timeout and retries values as set in object.
 * \ingroup Socket
 * Target Socket_t must have been fully initialised by tb_Connect or tb_initServer. Read result is appended in 'msg' String_t.  
 *
 * @return number of read bytes, or -1 if error.
 * Example:
 * \code
 * ...
 * String_t S = tb_String(NULL);
 * Socket_t So = tb_Socket(TB_TCP_UX, "/tmp/my_unix_sock", 0);
 * tb_Connect(So, 1, 1);
 * int rc;
 *
 * while(( rc = tb_readSock(So, S, 1024)) > 0);
 * switch( rc ) {
 * case -1: // error occurs
 * case  0: // read reached eof (or timed out)
 * ...
 * \endcode
 * S will contains a concatened string of all 1024's buffers read 
 *
 * other Examples : 
 * see test/srv_test.c , test/socket_test.c in build tree
 *
 * \remarks ERROR:
 * in case of error tb_errno will be set to :
 * - TB_ERR_INVALID_OBJECT : So not a TB_SOCKET
 * - TB_ERR_BAD : msg is not a TB_STRING
 * 
 * @see tb_Socket, tb_writeSock, tb_writeSockBin, tb_readSockLine
*/
int tb_readSock(Socket_t S, tb_Object_t Msg, int maxlen) {
  fd_set set ;
  struct timeval tps ;
  int rc, retval = 0;
	sock_members_t So;
	char buff[maxlen+1];

	no_error;

	if(! TB_VALID(S,   TB_SOCKET)) {
		set_tb_errno(TB_ERR_INVALID_TB_OBJECT);
		return TB_ERR;
	}

	if(! TB_VALID(Msg, TB_STRING) && ! TB_VALID(Msg, TB_RAW)) {
		set_tb_errno(TB_ERR_BAD);
		return TB_ERR;
	}

#ifdef WITH_XTI
	if( XSock(S)->addr_family   == TB_X25 ) {
		return tb_readSock_X25(S, Msg, maxlen);
	}
#endif


 
	So = XSock(S);


	if( So->buffer != NULL && tb_getSize(So->buffer) >0) {
		int n;
		n = TB_MIN( (maxlen), (tb_getSize(So->buffer)));
		tb_notice("readSock: already %d bytes in buffer\n", tb_getSize(So->buffer));
		if( n ) {
			if( tb_isA(Msg) == TB_STRING) {
				tb_StrnAdd(Msg, n, -1, "%S", So->buffer);
			} else {
			tb_RawAdd(Msg, n, -1, S2sz(So->buffer));
			}
			tb_StrDel(So->buffer, 0, n);
			if( n == maxlen) {
				return n;
			} else {
				maxlen -= n;
				retval = n;
			}
		}
	} 

	restart_r_select:

  FD_ZERO(&set);
  FD_SET(So->sock, &set);
  tb_getSockTO(S, &(tps.tv_sec), &(tps.tv_usec));

  rc = select(So->sock+1, &set, NULL, NULL, &tps);
  switch (rc)
    {
    case -1:
			if( errno == EINTR ) goto restart_r_select;
      tb_warn("tb_readSock[%d]: select failed (%s)\n", 
							 So->sock, strerror(errno)); 
      // invalid fd ==> we're disconnected
      if( errno == EBADF ) So->status = TB_DISCONNECTED;
			set_tb_errno(TB_ERR_DISCONNECTED);
      retval = TB_ERR;
      break; 
    case 0:
      /* Time out */
      tb_notice("tb_readSock[%d]: select timed out\n", So->sock); 
      So->status = TB_TIMEDOUT;
      retval = TB_KO;
			break ;
    default:
			if( ! FD_ISSET(So->sock, &set)) {
				tb_notice("tb_readSock[%d]: select rc=%d but fd is not ready\n", 
									So->sock, rc); 
				retval = TB_KO;
				break ;
			}
		restart_r_read:
#ifdef WITH_SSL
			if( So->ssl ) {
				tb_info("SSL_read: try to read %d bytes\n", maxlen);
				rc = SSL_read(XSsl(S)->cx, buff, maxlen);
				switch (SSL_get_error(XSsl(S)->cx,rc)) {
				case SSL_ERROR_NONE:
					buff[rc] = 0;
					tb_StrAdd(Msg, -1, "%s", buff);
					if( rc < maxlen ) {
						tb_info("SSL_read: got only %d/%d\n", rc, maxlen);
						maxlen -= rc;
						goto restart_r_select;
					}
					return rc;
				case SSL_ERROR_SYSCALL:
					if( errno ) {
						tb_warn("tb_readSock[%d(SSL)]: read error (%s)\n",
										 So->sock, strerror(errno));
					}
					/* fall through */
				case SSL_ERROR_WANT_WRITE:
				case SSL_ERROR_WANT_READ:
				case SSL_ERROR_WANT_X509_LOOKUP:
				case SSL_ERROR_ZERO_RETURN:
				case SSL_ERROR_SSL:
					ERR_print_errors_fp(stderr);
					return TB_ERR;
				}
			} else {
				set_nonblock_flag(So->sock, 1);
				rc = read(So->sock, buff, maxlen);
				set_nonblock_flag(So->sock, 0);
			}
#else
			set_nonblock_flag(So->sock, 1);
			rc = read(So->sock, buff, maxlen);
			set_nonblock_flag(So->sock, 0);
#endif			

      switch( rc ) {
      case -1:
				if( errno == EINTR ) goto restart_r_read;
				if( errno != EWOULDBLOCK ) {
					tb_error("tb_readSock[%d]: read error (%s)\n", So->sock, strerror(errno));
					retval = TB_ERR;
					So->status = TB_DISCONNECTED;
					break;
				}
      case 0:  // eof
				*buff = 0;
      default:
				retval += rc;
				tb_RawAdd(Msg, rc, -1, buff); 
				break ;
      }
      break;
    }
  return retval;
}
Пример #6
0
static int
run_proxy (void)
{
  int client_sock;
  int my_sock;
  int err;
  struct sockaddr_un clientname;
  size_t size;
  pthread_t  mythread;
  struct thread_data *thread_data;
  FILE *protocol_file;
  pthread_attr_t thread_attr;

  protocol_file = NULL;

  err = pthread_attr_init (&thread_attr);
  if (err)
    goto out;

  err = pthread_attr_setdetachstate (&thread_attr, PTHREAD_CREATE_DETACHED);
  if (err)
    goto out;

  if (opt.protocol_file)
    {
      protocol_file = fopen (opt.protocol_file, "a");
      if (! protocol_file)
	{
	  err = errno;
	  goto out;
	}
    }
  else
    protocol_file = stdout;

  err = create_server_socket (opt.listen_spec, &my_sock);
  if (err)
    goto out;

  while (1)
    {
      /* Accept new client.  */
      size = sizeof (clientname);
      client_sock = accept (my_sock,
			    (struct sockaddr *) &clientname,
			    &size);
      if (client_sock < 0)
	{
	  err = errno;
	  break;
	}

      /* Set IO mode to nonblicking.  */
      err = set_nonblock_flag (client_sock, 1);
      if (err)
	{
	  close (client_sock);
	  break;
	}

      /* Got new client -> handle in new process.  */

      thread_data = malloc (sizeof (*thread_data));
      if (! thread_data)
	{
	  err = errno;
	  break;
	}
      thread_data->client_sock = client_sock;
      thread_data->protocol_file = protocol_file;

      err = pthread_create (&mythread, &thread_attr, serve_client, thread_data);
      if (err)
	break;
    }
  if (err)
    goto out;

  /* ? */

 out:

  pthread_attr_destroy (&thread_attr);
  if (protocol_file)
    fclose (protocol_file);	/* FIXME, err checking.  */

  return err;
}