Exemplo n.º 1
0
void server(const char *bindAddr, int port, int ssl) {
    int soc_ec = -1, maxfd, res, nc;
    fd_set set_read;
    fd_set set_write;
    struct sockaddr_in addrS;
    char methods[2];

#ifdef _WIN32
    WSADATA wsaData;
    int wsaInit = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (wsaInit != 0) {
        ERROR(L_NOTICE, "WSAStartup failed: %d\n", wsaInit);
        exit(1);
    }
#endif

    s_socks_conf conf;
    s_socks_server_config config;
    conf.config.srv = &config;

    char versions[] = { SOCKS5_V,
                        SOCKS4_V
                      };

    config.allowed_version = versions;
    config.n_allowed_version = sizeof(versions);

    if ( globalArgsServer.fileauth[0] != 0 ) {
        methods[0] = 0x02;
        --config.n_allowed_version; /* Disable socks4 don't support auth */
    } else {
        methods[0] = 0x00;
    }


    config.allowed_method = methods;
    config.n_allowed_method = 1;
    config.check_auth = check_auth;

    /* Init client tab */
    for (nc = 0; nc < MAXCLI; nc++)
        init_client (&tc[nc], nc, M_SERVER, &conf);

    if(bindAddr[0] == 0)
        soc_ec = new_listen_socket (NULL, port, 0, &addrS);
    else
        soc_ec = new_listen_socket (bindAddr, port, 0, &addrS);

    if (soc_ec < 0) goto fin_serveur;


#ifndef _WIN32
    if ( globalArgsServer.daemon == 1 ) {
        TRACE(L_NOTICE, "server: mode daemon ...");
        if ( daemon(0, 0) != 0 ) {
            perror("daemon");
            exit(1);
        }
        writePID(PID_FILE);
    }

    bor_signal (SIGINT, capte_fin, SA_RESTART);

    /* Need in daemon to remove the PID file properly */
    bor_signal (SIGTERM, capte_fin, SA_RESTART);
    bor_signal (SIGPIPE, capte_sigpipe, SA_RESTART);
    /* TODO: Find a better way to exit the select and recall the init_select
     * SIGUSR1 is send by a thread to unblock the select */
    bor_signal (SIGUSR1, capte_usr1, SA_RESTART);
#endif

    while (boucle_princ) {
        init_select_server (soc_ec, tc, &maxfd, &set_read, &set_write);

        res = select (maxfd+1, &set_read, &set_write, NULL, NULL);

        if (res > 0) { /* Search eligible sockets */

            if (FD_ISSET (soc_ec, &set_read))
                new_connection (soc_ec, tc, ssl);

            for (nc = 0; nc < MAXCLI; nc++) {
                dispatch_server(&tc[nc], &set_read, &set_write);
            }

        } else if ( res == 0) {

        } else if (res < 0) {
            if (errno == EINTR) ; /* Received signal, it does nothing */
            else {
                perror ("select");
                goto fin_serveur;
            }
        }
    }

fin_serveur:
#ifdef HAVE_LIBSSL
    if (globalArgsServer.ssl == 1)
        ssl_cleaning();
#endif
    TRACE(L_NOTICE, "server: closing sockets ...");
    close_log();
    for (nc = 0; nc < MAXCLI; nc++) disconnection(&tc[nc]);
    if (soc_ec != -1) CLOSE_SOCKET(soc_ec);
    if ( globalArgsServer.daemon == 1 )	removePID(PID_FILE);

#ifdef _WIN32
        WSACleanup();
#endif
}
Exemplo n.º 2
0
void server_relay(int port, int listen, int ssl) {
    int soc_ec_cli = -1, soc_ec = -1, maxfd, res, nc;
    fd_set set_read;
    fd_set set_write;
    struct sockaddr_in addrS;


#ifdef _WIN32
    WSADATA wsaData;
    int wsaInit = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (wsaInit != 0) {
        ERROR(L_NOTICE, "WSAStartup failed: %d\n", wsaInit);
        exit(1);
    }
#endif

    /* Init client tab */
    for (nc = 0; nc < MAXCLI; nc++)
        init_socket(&socks_pool[nc]);

    for (nc = 0; nc < MAXCLI; nc++)
        init_client (&tc[nc], nc, 0, NULL);

    TRACE(L_NOTICE, "server: set listening client socks relay ...");
    soc_ec = new_listen_socket (NULL, port, MAXCLI, &addrS);
    if (soc_ec < 0) goto fin_serveur;

    TRACE(L_NOTICE, "server: set server relay ...");
    soc_ec_cli = new_listen_socket (NULL, listen, MAXCLI, &addrS);
    if (soc_ec_cli < 0) goto fin_serveur;


#ifndef _WIN32
    if ( globalArgs.background == 1 ) {
        TRACE(L_NOTICE, "server: background ...");
        if ( daemon(0, 0) != 0 ) {
            perror("daemon");
            exit(1);
        }
    }

    bor_signal (SIGINT, capte_fin, SA_RESTART);

    /* TODO: Find a better way to exit the select and recall the init_select
     * SIGUSR1 is send by a thread to unblock the select */
    bor_signal (SIGUSR1, capte_usr1, SA_RESTART);
#endif


    while (boucle_princ) {
        init_select_reverse(soc_ec, soc_ec_cli, tc, &maxfd, &set_read, &set_write);

        res = select (maxfd+1, &set_read, &set_write, NULL,NULL);

        if (res > 0) {  /* Search eligible sockets */

            if (FD_ISSET (soc_ec, &set_read))
                new_connection_socket (soc_ec, socks_pool, ssl);

            if (FD_ISSET (soc_ec_cli, &set_read))
                new_connection_reverse (soc_ec_cli, tc, socks_pool);

            for (nc = 0; nc < MAXCLI; nc++) {
                dispatch_server(&tc[nc], &set_read, &set_write);
            }
        } else if ( res == 0) {
            /* If timeout was set in select and expired */
        } else if (res < 0) {
            if (errno == EINTR) ;  /* Received signal, it does nothing */
            else {
                perror ("select");
                goto fin_serveur;
            }
        }
    }

fin_serveur:
#ifdef HAVE_LIBSSL
    if (ssl == 1)
        ssl_cleaning();
#endif
    printf ("Server: closing sockets ...\n");
    if (soc_ec != -1) CLOSE_SOCKET(soc_ec);
    for (nc = 0; nc < MAXCLI; nc++) close_socket(&socks_pool[nc]);
    for (nc = 0; nc < MAXCLI; nc++) disconnection(&tc[nc]);

#ifdef _WIN32
    WSACleanup();
#endif
}
Exemplo n.º 3
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() */