view seobeo/s_ssl.c @ 71:75de5903355c

Giagantic changes that update Dowa library to be more align with stb style array and hashmap. Updated Seobeo to be caching on server side instead of file level caching. Deleted bunch of things I don't really use.
author June Park <parkjune1995@gmail.com>
date Sun, 28 Dec 2025 20:34:22 -0800
parents 6626ec933933
children 70401cf61e97
line wrap: on
line source

#include "seobeo/seobeo.h"

#ifndef SEOBEO_NO_SSL

void Seobeo_Web_SSL_Init()
{
  SSL_load_error_strings();
  OpenSSL_add_ssl_algorithms();
}

void Seobeo_Web_SSL_Cleanup(void)
{
  EVP_cleanup(); // I don't think these are needed...
}

int Seobeo_SSL_Setup_Client(Seobeo_Handle *p_handle, const char *host, int socket_fd)
{
  if (!p_handle) return -1;

  printf("USE SSL\n\n");
  Seobeo_Web_SSL_Init();
  p_handle->ssl_ctx = SSL_CTX_new(TLS_client_method());
  if (!p_handle->ssl_ctx)
  {
    fprintf(stderr, "SSL_CTX_new failed\n");
    ERR_print_errors_fp(stderr);
    return -1;
  }

  SSL_CTX_set_default_verify_paths(p_handle->ssl_ctx);

  p_handle->ssl = SSL_new(p_handle->ssl_ctx);
  if (!p_handle->ssl)
  {
    fprintf(stderr, "SSL_new failed\n");
    ERR_print_errors_fp(stderr);
    SSL_CTX_free(p_handle->ssl_ctx);
    p_handle->ssl_ctx = NULL;
    return -1;
  }

  SSL_set_fd(p_handle->ssl, socket_fd);
  SSL_set_tlsext_host_name(p_handle->ssl, host);

  // Blocking for TLS handshake
  fcntl(socket_fd, F_SETFL, 0);

  if (SSL_connect(p_handle->ssl) != 1)
  {
    fprintf(stderr, "SSL_connect failed\n");
    ERR_print_errors_fp(stderr);
    SSL_free(p_handle->ssl);
    SSL_CTX_free(p_handle->ssl_ctx);
    p_handle->ssl = NULL;
    p_handle->ssl_ctx = NULL;
    return -1;
  }

  return 0;
}

void Seobeo_SSL_Cleanup(Seobeo_Handle *p_handle)
{
  if (!p_handle) return;

  if (p_handle->ssl)
  {
    SSL_shutdown(p_handle->ssl);
    SSL_free(p_handle->ssl);
    p_handle->ssl = NULL;
  }

  if (p_handle->ssl_ctx)
  {
    SSL_CTX_free(p_handle->ssl_ctx);
    p_handle->ssl_ctx = NULL;
  }
}

int32 Seobeo_SSL_Write(Seobeo_Handle *p_handle, const uint8 *data, uint32 length)
{
  if (!p_handle || !p_handle->ssl) return -1;

  int n = SSL_write(p_handle->ssl, data, length);
  if (n < 0)
  {
    int err = SSL_get_error(p_handle->ssl, n);
    if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
    {
      // caller must wait for socket readiness and retry
      return 0;
    }
    ERR_print_errors_fp(stderr);
    return -1;
  }
  return n;
}

int32 Seobeo_SSL_Read(Seobeo_Handle *p_handle, uint8 *buffer, uint32 length)
{
  if (!p_handle || !p_handle->ssl) return -1;

  int32 read_size = (int32)SSL_read(p_handle->ssl, buffer, length);
  if (read_size <= 0)
  {
    int err = SSL_get_error(p_handle->ssl, read_size);
    switch (err)
    {
      case SSL_ERROR_WANT_READ:
      case SSL_ERROR_WANT_WRITE:
        return 0;
      case SSL_ERROR_ZERO_RETURN:
      default:
        // TODO: Handle these errors
        return -2;
    }
  }
  return read_size;
}

#else

// Stub implementations when SSL is disabled
void Seobeo_Web_SSL_Init() {}
void Seobeo_Web_SSL_Cleanup(void) {}
int Seobeo_SSL_Setup_Client(Seobeo_Handle *p_handle, const char *host, int socket_fd)
{
  (void)p_handle; (void)host; (void)socket_fd;
  fprintf(stderr, "SSL support not compiled in\n");
  return -1;
}
void Seobeo_SSL_Cleanup(Seobeo_Handle *p_handle) { (void)p_handle; }
int32 Seobeo_SSL_Write(Seobeo_Handle *p_handle, const uint8 *data, uint32 length)
{
  (void)p_handle; (void)data; (void)length;
  return -1;
}
int32 Seobeo_SSL_Read(Seobeo_Handle *p_handle, uint8 *buffer, uint32 length)
{
  (void)p_handle; (void)buffer; (void)length;
  return -1;
}

#endif