ssl_write

前言

關於TCP/IP和OPENSSL相關的描述我想很多人都知道,這裏也不做什麼陳述,如果剛接觸的話可以去搜搜相關的文章,有很多寫的不錯的例子讓你來更充分地瞭解他們。

這裏的示例是由於要用到TLS1.2協議中的AEAD模式。

話不多說,直接上代碼。。。

TCP封裝

int setup_tcp_connect(char *ip, char *port)
{
    struct sockaddr_in sin;
    int sockfd;
    int res;
    struct timeval timeout = {60,0};
    int buflen = DEVICE_INFO_ARRAY_MAX_SIZE*240;   //這裏我設置了240K的發送緩衝區大小

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    memset(&sin, 0, sizeof(struct sockaddr_in));

    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = inet_addr(ip);
    sin.sin_port = htons(atoi(port));

    if(connect(sockfd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
        printf("[%s:%d] Socket connect error!error msg == %s\n", __FUNCTION__, __LINE__, strerror(errno));
        close(sockfd);
        return -1;
    }

    if(setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(timeout)) < 0) {
        printf("[%s:%d] Setsockopt send timeout fail\n", __FUNCTION__, __LINE__);
        return -1;
    }

    if(setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&buflen, 4) < 0) {
        printf("[%s:%d] Setsockopt sendbuffer fail\n", __FUNCTION__, __LINE__);
        return -1;
    }

    if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&timeout, sizeof(timeout)) < 0) {
        printf("[%s:%d] Setsockopt rcv fail\n", __FUNCTION__, __LINE__);
        return -1;
    }


    printf("[%s:%d] TCP connect success\n", __FUNCTION__, __LINE__);
    return sockfd;
}

SSL封裝

SSL *setup_ssl_connect(int sockfd, SSL_CTX *pssl_ctx)
{
    const char *cipher_list = "ECDHE-ECDSA-AES128-GCM-SHA256";    //這裏的cipher_list是與服務器協商好的加密套件,這裏以其中一個爲例
    SSL_METHOD *meth = NULL;
    SSL *pssl = NULL;
    int len = 0;
    int seed_init[DEVICE_INFO_ARRAY_SIZE] = {0};

    OpenSSL_add_ssl_algorithms();
    SSL_load_error_strings();

    meth = (SSL_METHOD *)TLSv1_2_client_method();
    pssl_ctx = SSL_CTX_new(meth);
    if(pssl_ctx == NULL) {
        printf("[%s:%d] SSL CTX NEW error!\n", __FUNCTION__, __LINE__);
        ERR_print_errors_fp(stderr);
        return NULL;
    }

    srand((unsigned)time(NULL));
    for(len = 0; len < 100; len++) {
        seed_init[len] = rand();
    }
    
    RAND_seed(seed_init, sizeof(seed_init));
    SSL_CTX_set_cipher_list(pssl_ctx, cipher_list);
    SSL_CTX_set_mode(pssl_ctx, SSL_MODE_AUTO_RETRY);

    //setup ssl
    pssl = SSL_new(pssl_ctx);
    if(SSL_set_fd(pssl, sockfd) <= 0) {
        printf("[%s:%d] SSL set fd error\n", __FUNCTION__, __LINE__);
        goto error;
    }
    
    SSL_set_mode(pssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);

    if(SSL_connect(pssl) <= 0) {
        printf("[%s:%d] SSL connect error\n", __FUNCTION__, __LINE__);
        ERR_print_errors_fp(stderr);
        goto error;
    }
    printf("[%s:%d] SSL connect success\n", __FUNCTION__, __LINE__);
    return pssl;
error:
    if(SSL_shutdown(pssl) != 1) {
        SSL_shutdown(pssl);
    }
    SSL_free(pssl);
    SSL_CTX_free(pssl_ctx);
    return NULL;
}

int send_requset(char *request_data, long int len, SSL *pssl)
{
    int ret,res;
    long int count = 0;
    
    if(pssl != NULL && request_data != NULL && len > 0) {
    	pthread_mutex_lock(&write_lock);
        while(1) {
            res = SSL_write(pssl, (void *)request_data + count, len - count);
            ret = SSL_get_error(pssl, res);
            if(ret == SSL_ERROR_NONE) {
                if(res > 0) {
                    count += res;
                    if(count >= len) {
                        break;
                    }
                    continue;
                } else {
                    printf("[%s:%d] SSL write error\n", __FUNCTION__, __LINE__);
                    ERR_print_errors_fp(stderr);
                }
            } else if(ret == SSL_ERROR_WANT_READ) {
                continue;
            } else if(ret == SSL_ERROR_WANT_WRITE) {
                continue;
            } else {
                printf("[%s:%d] SSL write error, error code == %d\n", __FUNCTION__, __LINE__, ret);
                ERR_print_errors_fp(stderr);
                break;
            }
        }
        pthread_mutex_unlock(&write_lock);
        return count;
    } else {
        printf("[%s:%d] Send request pssl/request_data/len is NULL\n", __FUNCTION__, __LINE__);
        return -1;
    }
}

備註:按道理這裏的ssl_write是不需要加鎖的,不過這個是按照自己這邊的項目情況而定,沒有什麼特殊的設定的話不需要加鎖

之前在網上也有搜到ssl_write的返回值代表什麼意思,這裏推薦給大家:
點擊這裏查看

關於這兩個的代碼就是這些,下一篇再說ssl_read的相關實現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章