Esempio n. 1
0
/* Create a connection to a host trough a socks5
 * If success s contain a socket to server
 *
 * If listen port != 0, it means bind mode,
 * so host and port will be ignored
 *
 * Return:
 *  -1, connection error, unavailable socks server
 *   0, connection error, socks5 negociation
 *   1, connection establish, socket is set in struct s
 */
int new_socket_with_socks(s_socket *s,
		char *sockshost, int socksport,
		char *username, char *password,
		char *host, int port, int listen,
		int version, int ssl, int cmd)
{
	int maxfd = 0, res;
	fd_set set_read, set_write;

	s_socks_conf conf;
	s_socks_client_config config;
	conf.config.cli = &config;

	char method[] =  { 0x00, 0x02 };
	conf.config.cli->n_allowed_method = 2;
	conf.config.cli->allowed_method = method;

	/* If no username or password  we don't use auth */
	if ( username == NULL || password == NULL )
		--conf.config.cli->n_allowed_method;

	conf.config.cli->loop = 1;
	conf.config.cli->cmd = cmd;
	conf.config.cli->host = host;
	conf.config.cli->port = port;
	conf.config.cli->listen = listen;
	conf.config.cli->version = version;
	conf.config.cli->username = username;
	conf.config.cli->password = password;

	//memcpy(&conf.config, &config, sizeof(s_socks_serv_cli_config));

    s_client c;
	init_client (&c, 0, M_CLIENT, &conf);

	c.soc.soc = new_client_socket(sockshost, socksport,
		&c.soc.adrC, &c.soc.adrS);
	if ( c.soc.soc < 0 ){
		return -1;
	}

#ifdef HAVE_LIBSSL
	/* Init SSL here
	 */
	if (ssl == 1){
		TRACE(L_DEBUG, "client: socks5 enable ssl ...");
		c.soc.ssl = ssl_neogiciate_client(c.soc.soc);
		if ( c.soc.ssl == NULL ){
			ERROR(L_VERBOSE, "client: ssl error");
			return -3;
		}
		TRACE(L_DEBUG, "client: ssl ok.");
	}
#endif /* HAVE_LIBSSL */

    /* Select loop */
    while (conf.config.cli->loop  == 1 && c.soc.soc != -1) {

		FD_ZERO (&set_read);
		FD_ZERO (&set_write);
		maxfd = 0;

		/* Adds the socket in read fds */
		init_select_client(&c.soc, &c.socks, &c.buf, &maxfd, &set_read, &set_write);

		res = select (maxfd+1, &set_read, &set_write, NULL, NULL);
        if (res > 0) {
            dispatch_client(&c, &set_read, &set_write);
        } else if ( res == 0){

        }else if (res < 0) {
            if (errno == EINTR) ; /* Received signal, it does nothing */
            else { perror ("select"); disconnection(&c); return -1; }
        }
	}

	memcpy(s, &c.soc, sizeof(s_socket));
	return (c.soc.soc >= 0);
}
Esempio n. 2
0
int main(int argc, char **argv) {
	char buf[1024];

	fd_set *     readselect  = malloc(sizeof(fd_set));
	fd_set *     writeselect = malloc(sizeof(fd_set));
	fd_set *     errorselect = malloc(sizeof(fd_set));
	unsigned int maxfd = 3;

	readsockets  = array_init(); readsockets->name = "read";
	writesockets = array_init(); writesockets->name = "write";
	errorsockets = array_init(); errorsockets->name = "error";

	buffer_socket * stdin_sock = malloc(sizeof(buffer_socket));
	stdin_sock->type = SOCKTYPE_LOCAL;
	stdin_sock->fd   = STDIN_FILENO;
	ringbuffer_init(&stdin_sock->rxbuffer);
	ringbuffer_init(&stdin_sock->txbuffer);

	readsockets = array_push(readsockets, stdin_sock);
	errorsockets = array_push(errorsockets, stdin_sock);

	char * printer_port = DEFAULT_PORT;
	int printer_baud = DEFAULT_BAUD;

	// TODO: parse command line options

	printer_socket *printer = new_printer_socket(printer_port, printer_baud);

	file_socket *file = NULL;

	/***********************************************************************\
	*                                                                       *
	* Now set up network sockets                                            *
	*                                                                       *
	\***********************************************************************/

	new_listen_socket(DEFAULT_LISTEN_PORT, SOCKTYPE_CLIENT);
	new_listen_socket(DEFAULT_LISTEN_PORT + 1, SOCKTYPE_HTTP);

	/***********************************************************************\
	*                                                                       *
	* Main Loop                                                             *
	*                                                                       *
	\***********************************************************************/

	int running = 1;

	while (running) {
		FD_ZERO(readselect);
		FD_ZERO(writeselect);
		FD_ZERO(errorselect);
		for (int i = 0; i < readsockets->length; i++) {
			local_socket *ls = ((local_socket *) readsockets->data[i]);
			int fd = ls->fd;
			//printf("check read %d\n", ((local_socket *) readsockets->data[i])->fd);
			if ((ls->type == SOCKTYPE_PRINTER) || (printer->tokens > 0)) {
				FD_SET(fd, readselect);
				if (fd >= maxfd)
					maxfd = fd + 1;
			}
		}
		for (int i = 0; i < writesockets->length; i++) {
			local_socket *ls = ((local_socket *) writesockets->data[i]);
			int fd = ls->fd;
			//printf("check write %d\n", ((local_socket *) writesockets->data[i])->fd);
			if ((ls->type != SOCKTYPE_PRINTER) || (printer->tokens > 0)) {
				FD_SET(fd, writeselect);
				if (fd >= maxfd)
					maxfd = fd + 1;
			}
		}
		for (int i = 0; i < errorsockets->length; i++) {
			local_socket *ls = ((local_socket *) errorsockets->data[i]);
			int fd = ls->fd;
			//printf("check error %d\n", ((local_socket *) errorsockets->data[i])->fd);
			FD_SET(((local_socket *) errorsockets->data[i])->fd, errorselect);
			if (fd >= maxfd)
				maxfd = fd + 1;
		}
		select(maxfd, readselect, writeselect, errorselect, NULL);

		/*******************************************************************\
		*                                                                   *
		* Check Errors                                                      *
		*                                                                   *
		\*******************************************************************/
		for (int i = 0; i < errorsockets->length; i++) {
			local_socket *s = (local_socket *) errorsockets->data[i];
			if (FD_ISSET(s->fd, errorselect)) {
				printf("error on %d: %p\n", s->fd, s);
				switch (s->type) {
					case SOCKTYPE_LOCAL:
						break;
					case SOCKTYPE_PRINTER:
						break;
					case SOCKTYPE_CLIENT:
						break;
					case SOCKTYPE_LISTEN:
						break;
				} /* switch s->type */
			} /* if FD_ISSET fd, errorselect */
		} /* for errorsockets */

		/*******************************************************************\
		*                                                                   *
		* Check Readable Sockets                                            *
		*                                                                   *
		\*******************************************************************/
		for (int i = 0; i < readsockets->length; i++) {
			local_socket *s = (local_socket *) readsockets->data[i];
			if (FD_ISSET(s->fd, readselect)) {
				//printf("read %d (type %d)\n", s->fd, s->type);
				switch (s->type) {
					case SOCKTYPE_LOCAL: {
						buffer_socket *sock = (buffer_socket *) s;
						unsigned int r = ringbuffer_writefromfd(&sock->rxbuffer, s->fd, ringbuffer_canwrite(&sock->rxbuffer));
						if (r == 0) {
							printf("EOF on stdin, exiting...\n");
							exit(0);
						}
						break;
					}
					case SOCKTYPE_CLIENT: {
						client_socket *sock = (client_socket *) s;
						unsigned int r = ringbuffer_writefromfd(&sock->inbuffer, s->fd, ringbuffer_canwrite(&sock->inbuffer));
						//printf("writefromfd %p %d %d got %d nl %d\n", &sock->rxbuffer, s->fd, ringbuffer_canwrite(&sock->rxbuffer), r, sock->rxbuffer.nl);
						if (r == 0) {
							sock2a(&sock->addr, buf, BUFFER_SIZE);
							printf("client %s disconnected\n", buf);
							close(sock->fd);
							readsockets = array_delete(readsockets, sock);
							writesockets = array_delete(writesockets, sock);
							errorsockets = array_delete(errorsockets, sock);
							free(sock);
							sock = NULL;
						}
						else if (sock->inbuffer.nl > 0) {
							char linebuffer[256];
							while (ringbuffer_peekline(&sock->inbuffer, linebuffer, sizeof(linebuffer))) {
								switch (detect_line_type(linebuffer)) {
									case LINETYPE_GCODE: {
										unsigned int i = ringbuffer_readline(&sock->rxbuffer, linebuffer, sizeof(linebuffer));
										ringbuffer_write(&sock->rxbuffer, linebuffer, i);
										break;
									};
									case LINETYPE_SIMPLECMD: {
										unsigned int i = ringbuffer_readline(&sock->rxbuffer, linebuffer, sizeof(linebuffer));
										parse_line(linebuffer);
										break;
									};
								}
							}
						}
						break;
					}
					case SOCKTYPE_PRINTER: {
						//printf("can read printer\n");
						printer_socket *sock = (printer_socket *) s;
						unsigned int r = ringbuffer_writefromfd(&sock->rxbuffer, s->fd, BUFFER_SIZE);
						if (r == 0) {
							//printf(" %d bytes: printer disconnected, trying to reconnect...\n", r);
							close(s->fd);
							readsockets = array_delete(readsockets, sock);
							writesockets = array_delete(writesockets, sock);
							errorsockets = array_delete(errorsockets, sock);
							free(sock);
							sock = NULL;
							sock = new_printer_socket(printer_port, printer_baud);
							readsockets = array_push(readsockets, sock);
							errorsockets = array_push(errorsockets, sock);
						}
						else {
							//printf(" %d bytes, %d newlines", r, sock->rxbuffer.nl);
							while (sock->rxbuffer.nl > 0) {
								char line[BUFFER_SIZE];
								int r = ringbuffer_readline(&sock->rxbuffer, line, BUFFER_SIZE);
								if (sock->lastmsgsock->fd > 2)
									printf("< %s", line);
								int m = snprintf(buf, BUFFER_SIZE, "< %s", line);
								if (sock->lastmsgsock->type == SOCKTYPE_LOCAL) {
									int i = 0;
									do {
										i += write(sock->lastmsgsock->fd, &buf[i], m - i);
									} while (i < m);
								}
								else if (sock->lastmsgsock->type == SOCKTYPE_CLIENT) {
									//printf("client type\n");
									client_socket *cs = (client_socket *) sock->lastmsgsock;
									ringbuffer_write(&cs->txbuffer, line, r);
									if (array_indexof(writesockets, cs) == -1) {
										writesockets = array_push(writesockets, cs);
										//printf("pushed %p/%d to writesockets\n", cs, cs->socket.fd);
									}
								}
								if (strncmp(line, "ok", 2) == 0) {
									//fprintf(stderr, "got token!");
									if (sock->tokens < sock->maxtoken)
										sock->tokens++;
									for (int i = 0; i < errorsockets->length; i++) {
										if (((local_socket *) errorsockets->data[i])->type == SOCKTYPE_CLIENT)
											readsockets = array_push(readsockets, errorsockets->data[i]);
									}
									if (file != NULL)
										writesockets = array_push(writesockets, sock);
									//fprintf(stderr, " tokens: %d\n", sock->tokens);
								}
								else {
									//fprintf(stderr, "no token\n");
								}
							}
						}
						break;
					}
					case SOCKTYPE_LISTEN: {
						listen_socket *ls = (listen_socket *) s;
						if (ls->protocol == SOCKTYPE_HTTP) {
							new_http_socket(ls);
						}
						else if (ls->protocol == SOCKTYPE_CLIENT) {
							new_client_socket(ls);
						}
						break;
					}
					case SOCKTYPE_FILE: {
						break;
					}
					case SOCKTYPE_HTTP: {
						http_socket *sock = (http_socket *) s;
						unsigned int r = ringbuffer_writefromfd(&sock->rxbuffer, s->fd, ringbuffer_canwrite(&sock->rxbuffer));
						if (r == 0) {
							sock2a(&sock->addr, buf, BUFFER_SIZE);
							printf("client %s disconnected\n", buf);
							close(sock->fd);
							readsockets = array_delete(readsockets, sock);
							writesockets = array_delete(writesockets, sock);
							errorsockets = array_delete(errorsockets, sock);
							free(sock);
							sock = NULL;
						}
						else {
						}
						break;
					}
				} /* switch s->type */
			} /* if FD_ISSET fd, readselect */
		} /* for readsockets */

		/*******************************************************************\
		*                                                                   *
		* Check Writable Sockets                                            *
		*                                                                   *
		\*******************************************************************/
		for (int i = 0; i < writesockets->length; i++) {
			local_socket *s = (local_socket *) writesockets->data[i];
			if (FD_ISSET(s->fd, writeselect)) {
				//printf("write %d", s->fd);
				switch (s->type) {
					case SOCKTYPE_LOCAL:
					case SOCKTYPE_CLIENT:
					case SOCKTYPE_HTTP: {
						//printf("write client socket\n");
						buffer_socket *sock = (buffer_socket *) s;
						if (ringbuffer_canread(&sock->txbuffer) > 0) {
							//printf("readtofd %d %p: %d\n", s->fd, &sock->txbuffer,
								ringbuffer_readtofd(&sock->txbuffer, s->fd);
							//);
						}
						if (ringbuffer_canread(&sock->txbuffer) == 0) {
							//printf("client txbuffer empty\n");
							writesockets = array_delete(writesockets, s);
						}
						break;
					}
					case SOCKTYPE_PRINTER: {
						printer_socket *sock = (printer_socket *) s;
						//printf("write: nl: %d\n", sock->txbuffer.nl);
						if (sock->rxbuffer.nl == 0) {
							int i = (sock->lastmsgindex + 1) % errorsockets->length;
							for (int j = 0; j <= errorsockets->length; j++) {
								buffer_socket * x = errorsockets->data[i];
								if (x->type == SOCKTYPE_LOCAL || x->type == SOCKTYPE_CLIENT || x->type == SOCKTYPE_FILE) {
									int r = ringbuffer_readline(&x->rxbuffer, buf, BUFFER_SIZE);
									ringbuffer_write(&printer->txbuffer, buf, r);
									sock->lastmsgsock = (local_socket *) x;
									sock->lastmsgindex = i;
									break;
								}
								i = (i + 1) % errorsockets->length;
							}
						}
						if (sock->txbuffer.nl > 0) {
							//printf("write: nl: %d\n", sock->txbuffer.nl);
							unsigned int r = ringbuffer_readline(&sock->txbuffer, buf, BUFFER_SIZE);
							buf[r] = 0;
							printf(">>> %s", buf);
							int i = 0;
							do {
								i += write(s->fd, &buf[i], r - i);
							} while (i < r);
							sock->tokens--;
							if (sock->tokens == 0) {
								for (int i = 0; i < errorsockets->length; i++) {
									if (((local_socket *) errorsockets->data[i])->type == SOCKTYPE_CLIENT)
										readsockets = array_delete(readsockets, errorsockets->data[i]);
								}
							}
						}
						else if ((sock->tokens > 0) && (file != NULL) && (file->paused == 0)) {
							if ((ringbuffer_canwrite(&file->rxbuffer) > 0) && (file->eof == 0)) {
								int w = ringbuffer_writefromfd(&file->rxbuffer, file->fd, BUFFER_SIZE);
								if (w == 0)
									file->eof = 1;
							}
							if (file->rxbuffer.nl > 0) {
								int r = ringbuffer_readline(&file->rxbuffer, buf, BUFFER_SIZE);
								buf[r] = 0;
								printf(">>> %s", buf);
								int i = 0;
								do {
									i += write(s->fd, &buf[i], r - i);
								} while (i < r);
								sock->tokens--;
							}
							else if (file->eof) {
								// file is completely printed
								printf("File %s complete. Print time: \n", file->filename);
								// TODO:close file
							}
						}
						if ((ringbuffer_canread(&sock->txbuffer) == 0) || (sock->tokens == 0))
							writesockets = array_delete(writesockets, sock);
						break;
					}
				} /* switch s->type */
			} /* if FD_ISSET fd, writeselect */
		} /* for writesockets */
	} /* while running */

	return 0;
} /* main() */