echoserver.cpp 3.41 KB
Newer Older
unknown's avatar
unknown committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/* echoserver.cpp */

#include "../../testsuite/test.hpp"


#ifndef NO_MAIN_DRIVER
    #define ECHO_OUT

    THREAD_RETURN YASSL_API echoserver_test(void*);
    int main(int argc, char** argv)
    {
        func_args args;

        args.argc = argc;
        args.argv = argv;

        echoserver_test(&args);
unknown's avatar
unknown committed
18 19
        yaSSL_CleanUp();

unknown's avatar
unknown committed
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
        return args.return_code;
    }

#endif // NO_MAIN_DRIVER


THREAD_RETURN YASSL_API echoserver_test(void* args)
{
#ifdef _WIN32
    WSADATA wsd;
    WSAStartup(0x0002, &wsd);
#endif

    SOCKET_T sockfd = 0;
    int      argc = 0;
    char**   argv = 0;

    set_args(argc, argv, *static_cast<func_args*>(args));

#ifdef ECHO_OUT
    FILE* fout = stdout;
    if (argc >= 2) fout = fopen(argv[1], "w");
    if (!fout) err_sys("can't open output file");
#endif

    tcp_listen(sockfd);

    SSL_METHOD* method = TLSv1_server_method();
    SSL_CTX*    ctx    = SSL_CTX_new(method);

    set_serverCerts(ctx);
    DH* dh = set_tmpDH(ctx);

    bool shutdown(false);

#if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER)
    // signal ready to tcp_accept
    func_args& server_args = *((func_args*)args);
    tcp_ready& ready = *server_args.signal_;
    pthread_mutex_lock(&ready.mutex_);
    ready.ready_ = true;
    pthread_cond_signal(&ready.cond_);
    pthread_mutex_unlock(&ready.mutex_);
#endif

    while (!shutdown) {
        sockaddr_in client;
        socklen_t   client_len = sizeof(client);
unknown's avatar
unknown committed
68 69
        int         clientfd = accept(sockfd, (sockaddr*)&client,
                                      (ACCEPT_THIRD_T)&client_len);
unknown's avatar
unknown committed
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
        if (clientfd == -1) err_sys("tcp accept failed");

        SSL* ssl = SSL_new(ctx);
        SSL_set_fd(ssl, clientfd);
        if (SSL_accept(ssl) != SSL_SUCCESS) err_sys("SSL_accept failed");

        char command[1024];
        int echoSz(0);
        while ( (echoSz = SSL_read(ssl, command, sizeof(command))) > 0) {
           
            if ( strncmp(command, "quit", 4) == 0) {
                printf("client sent quit command: shutting down!\n");
                shutdown = true;
                break;
            }
            else if ( strncmp(command, "GET", 3) == 0) {
                char type[]   = "HTTP/1.0 200 ok\r\nContent-type:"
                                " text/html\r\n\r\n";
                char header[] = "<html><body BGCOLOR=\"#ffffff\">\n<pre>\n";
                char body[]   = "greetings from yaSSL\n";
                char footer[] = "</body></html>\r\n\r\n";
            
                strncpy(command, type, sizeof(type));
                echoSz = sizeof(type) - 1;

                strncpy(&command[echoSz], header, sizeof(header));
                echoSz += sizeof(header) - 1;
                strncpy(&command[echoSz], body, sizeof(body));
                echoSz += sizeof(body) - 1;
                strncpy(&command[echoSz], footer, sizeof(footer));
                echoSz += sizeof(footer);

                if (SSL_write(ssl, command, echoSz) != echoSz)
                    err_sys("SSL_write failed");
                break;
            }
            command[echoSz] = 0;

        #ifdef ECHO_OUT
            fputs(command, fout);
        #endif

            if (SSL_write(ssl, command, echoSz) != echoSz)
                err_sys("SSL_write failed");
        }
        SSL_free(ssl);
    }

#ifdef _WIN32
    closesocket(sockfd);
#else
    close(sockfd);
#endif

    DH_free(dh);
    SSL_CTX_free(ctx);

    ((func_args*)args)->return_code = 0;
    return 0;
}