/* util.c */
#include <stdio.h>
#include <stdlib.h>
#include "util.h"

extern void
ws_time(struct timeval* tv)
{
  gettimeofday(tv, NULL);
} 

extern int
ws_time_diff(struct timeval* start, struct timeval* end)
{
  long sec  = end->tv_sec  - start->tv_sec;
  long usec = end->tv_usec - start->tv_usec;

  //fprintf(stderr, "%ld %ld %ld %ld %ld %ld\n", end->tv_sec, end->tv_usec, start->tv_sec, start->tv_usec, sec, usec);
  return (int )(sec * 1000 + usec / 1000);
}

static void out_with_nl(FILE* fp, char* s)
{
  fprintf(fp, "%s\r\n", s);
}

extern void
ws_print_reason(enum libwebsocket_callback_reasons reason)
{
  switch (reason) {
  case LWS_CALLBACK_ESTABLISHED:
    out_with_nl(stderr, "LWS_CALLBACK_ESTABLISHED");
    break;
  case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
    out_with_nl(stderr, "LWS_CALLBACK_CLIENT_CONNECTION_ERROR");
    break;
  case LWS_CALLBACK_CLIENT_ESTABLISHED:
    out_with_nl(stderr, "LWS_CALLBACK_CLIENT_ESTABLISHED");
    break;
  case LWS_CALLBACK_CLOSED:
    out_with_nl(stderr, "LWS_CALLBACK_CLOSED");
    break;
  case LWS_CALLBACK_RECEIVE:
    out_with_nl(stderr, "LWS_CALLBACK_RECEIVE");
    break;
  case LWS_CALLBACK_CLIENT_RECEIVE:
    //out_with_nl(stderr, "LWS_CALLBACK_CLIENT_RECEIVE");
    break;
  case LWS_CALLBACK_CLIENT_RECEIVE_PONG:
    out_with_nl(stderr, "LWS_CALLBACK_CLIENT_RECEIVE_PONG");
    break;
  case LWS_CALLBACK_CLIENT_WRITEABLE:
    //out_with_nl(stderr, "LWS_CALLBACK_CLIENT_WRITEABLE");
    break;
  case LWS_CALLBACK_SERVER_WRITEABLE:
    out_with_nl(stderr, "LWS_CALLBACK_SERVER_WRITEABLE");
    break;
  case LWS_CALLBACK_HTTP:
    out_with_nl(stderr, "LWS_CALLBACK_HTTP");
    break;
  case LWS_CALLBACK_FILTER_NETWORK_CONNECTION:
    out_with_nl(stderr, "LWS_CALLBACK_FILTER_NETWORK_CONNECTION");
    break;
  case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
    out_with_nl(stderr, "LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION");
    break;
  case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS: 
    out_with_nl(stderr, "LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS");
    break;
  case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS:
    out_with_nl(stderr, "LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS");
    break;
  case LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION:
    out_with_nl(stderr, "LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION");
    break;
  case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
    out_with_nl(stderr, "LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER");
    break;
  case LWS_CALLBACK_CONFIRM_EXTENSION_OKAY:
    out_with_nl(stderr, "LWS_CALLBACK_CONFIRM_EXTENSION_OKAY");
    break;
  case LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED:
    out_with_nl(stderr, "LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED");
    break;
  case LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH:
    out_with_nl(stderr, "LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH");
    break;
  case LWS_CALLBACK_CLOSED_HTTP:
    out_with_nl(stderr, "LWS_CALLBACK_CLOSED_HTTP");
    break;
  case LWS_CALLBACK_HTTP_FILE_COMPLETION:
    out_with_nl(stderr, "LWS_CALLBACK_HTTP_FILE_COMPLETION");
    break;
  case LWS_CALLBACK_HTTP_WRITEABLE:
    out_with_nl(stderr, "LWS_CALLBACK_HTTP_WRITEABLE");
    break;
  case LWS_CALLBACK_PROTOCOL_INIT:
    out_with_nl(stderr, "LWS_CALLBACK_PROTOCOL_INIT");
    break;
  case LWS_CALLBACK_PROTOCOL_DESTROY:
    out_with_nl(stderr, "LWS_CALLBACK_PROTOCOL_DESTROY");
    break;
    /* external poll() management support */
  case LWS_CALLBACK_ADD_POLL_FD:
    out_with_nl(stderr, "LWS_CALLBACK_ADD_POLL_FD");
    break;
  case LWS_CALLBACK_DEL_POLL_FD:
    out_with_nl(stderr, "LWS_CALLBACK_DEL_POLL_FD");
    break;
  case LWS_CALLBACK_SET_MODE_POLL_FD:
    //out_with_nl(stderr, "LWS_CALLBACK_SET_MODE_POLL_FD");
    break;
  case LWS_CALLBACK_CLEAR_MODE_POLL_FD:
    //out_with_nl(stderr, "LWS_CALLBACK_CLEAR_MODE_POLL_FD");
    break;
  }
}

extern void
ws_clear_ringbuffer(PER_SESSION_DATA* ps, int do_free)
{
  int i;

  ps->ringbuffer_tail = ps->ringbuffer_head = 0;
  for (i = 0; i < MAX_MESSAGE_QUEUE; i++) {
    if (do_free && ps->ringbuffer[i].payload)
      free(ps->ringbuffer[i].payload);

    ps->ringbuffer[i].payload = 0;
    ps->ringbuffer[i].len     = 0;
  }
}
