예제 #1
0
파일: server.c 프로젝트: tdunnick/phineas
/*
 * format up an HTTP response and return it
 */
DBUF *server_respond (int code, char *fmt, ...)
{
  int l, len, avail;
  va_list ap;
  char *ch;
  DBUF *b;
  char buf[4096];

  /*
   * note our response body is limited to 4096 bytes - only small
   * response is needed or allowed.
   */
  len = sprintf (buf, "<html><body>");
  avail = 4096 - (len * 2 + 4);
  va_start (ap, fmt);
  l = vsnprintf (buf + len, avail, fmt, ap);
  va_end (ap);
  if ((l > 0) && (l < avail))
    len += l;
  len += sprintf (buf + len, "</body></html>");
  /*
   * if we are no longer running, notify the client that we are
   * closing this connection.
   */
  b = dbuf_alloc ();
  dbuf_printf (b, "Status: %d\r\n"
    "Content-Length: %d\r\n"
    "Connection: %s\r\n\r\n%s",
    code, len, phineas_running () ? "Keep-alive" : "Close", buf);
  debug ("response:\n%s\n", dbuf_getbuf (b));
  return (b);
}
예제 #2
0
파일: qpoller.c 프로젝트: teapejon/phineas
/*
 * Poll all queues...
 * a thread, expected to be started from the TASKQ.  Note you must
 * re-register processors once this task exits.
 *
 * Note we expect sender_xml to have QueueInfo embedded!
 */
int qpoller_task (void *parm)
{
  int i,
      poll_interval,
      num_queues;
  QPOLLER *p;
  QPOLLERJOB *j;
  TASKQ *q;
  XML *xml = (XML *) parm;

  info ("Queue Poller starting\n");
  num_queues = xml_count (xml, QP_QUEUE);
  if ((poll_interval = xml_get_int (xml, QP_INFO".PollInterval")) < 1)
    poll_interval = 5;
  poll_interval *= 1000;
  if ((i = xml_get_int (xml, QP_INFO".MaxThreads")) < 1)
    i = 1;
  q = task_allocq (i, poll_interval);
  debug ("%d queues %d interval\n", num_queues, poll_interval);
  while (phineas_running ())
  {
    for (i = 0; i < num_queues; i++)
    {
      qpoller_poll (xml, i, q);
    }
    sleep (poll_interval);
  }
  debug ("Queue Poller shutting down...\n");
  task_stop (q);
  task_freeq (q);
  while ((j = QpollerJobs) != NULL)
  {
    QpollerJobs = j->next;
    free (j);
  }
  while ((p = Qpoller) != NULL)
  {
    Qpoller = p->next;
    free (p);
  }
  info ("Queue Poller exiting\n");
  return (0);
}
예제 #3
0
파일: server.c 프로젝트: tdunnick/phineas
/*
 * Listen for incoming connections until told to stop
 */
int server_listen (XML *xml, NETCON *conn, NETCON *ssl, SSL_CTX *ctx,
  int threads)
{
  char *ch;
  TASKQ *t;
  struct timeval timeout;
  fd_set fds;

  if ((conn == NULL) && (ssl == NULL))
    return (-1);

  t = task_allocq (threads, 2);
  timeout.tv_sec = 2;
  timeout.tv_usec = 0;

  /*
   * Keep servicing requests until they stop coming in AND we are
   * no longer running.  This insures a nice shutdown, although a
   * naughty client could keep us from shutting down by flooding us
   * with requests.  We could add a counter here to prevent that.
   */
  while (1)
  {
    FD_ZERO (&fds);
    if (conn != NULL)
      FD_SET (conn->sock, &fds);
    if (ssl != NULL)
      FD_SET (ssl->sock, &fds);
    if (select (2, &fds, NULL, NULL, &timeout) <= 0)
    {
      if (phineas_running ())
        continue;
      break;
    }
    if ((conn != NULL) && FD_ISSET (conn->sock, &fds))
      server_accept (xml, conn, NULL, t);
    if ((ssl != NULL) && FD_ISSET (ssl->sock, &fds))
      server_accept (xml, ssl, ctx, t);
  }
  task_stop (t);
  task_freeq (t);
  return (0);
}
예제 #4
0
/*
 * send a message
 * return non-zero if message not sent successful with completed
 * queue info for status and transport
 */
int ebxml_send (XML*xml, QUEUEROW *r, MIME *msg)
{
  DBUF *b;
  NETCON *conn;
  char host[MAX_PATH];	/* need buffers for redirect		*/
  char path[MAX_PATH];
  int port, route, timeout, delay, retry;
  SSL_CTX *ctx;
  char *rname, 		/* route name				*/
       *content, 	/* message content			*/
       buf[MAX_PATH];

  /* format up the message					*/
  if ((content = mime_format (msg)) == NULL)
  {
    queue_field_set (r, "PROCESSINGSTATUS", "done");
    queue_field_set (r, "TRANSPORTSTATUS", "failed");
    queue_field_set (r, "TRANSPORTERRORCODE", "failed formatting message");
    return (-1);
  }
  debug ("Send content:\n%s\n", content);

  /*
   * get connection info from the record route
   */
  if ((route = 
    cfg_route_index (xml, queue_field_get (r, "ROUTEINFO"))) < 0)
  {
    queue_field_set (r, "PROCESSINGSTATUS", "done");
    queue_field_set (r, "TRANSPORTSTATUS", "failed");
    queue_field_set (r, "TRANSPORTERRORCODE", "bad route");
    return (-1);
  }
  rname = cfg_route (xml, route, "Name");
  ctx = ebxml_route_ctx (xml, route);
  strcpy (host, cfg_route (xml, route, "Host"));
  port = atoi (cfg_route (xml, route, "Port"));
  if ((retry = atoi (cfg_route (xml, route, "Retry"))) == 0)
    retry = cfg_retries (xml);
  timeout = atoi (cfg_route (xml, route, "Timeout"));
  delay = cfg_delay (xml);
  strcpy (path, cfg_route (xml, route, "Path"));

sendmsg:

  info ("Sending ebXML %s:%d to %s\n", 
    r->queue->name, r->rowid, rname);
  debug ("opening connection socket on port=%d retrys=%d timeout=%d\n", 
    port, retry, timeout);
  if ((conn = net_open (host, port, 0, ctx)) == NULL)
  {
    error ("failed opening connection to %s:%d\n", host, port);
    goto retrysend;
  }
  				/* set read timeout if given	*/
  if (timeout)
  {
    net_timeout (conn, timeout * 1000);
    timeout <<= 1;		/* bump each try		*/
  }
  delay = 0;			/* connection OK, don't delay	*/
  queue_field_set (r, "MESSAGESENTTIME", ptime (NULL, buf));
  sprintf (buf, "POST %s HTTP/1.1\r\n", path);
  // ch = ebxml_beautify (ch);
  				/* all set... send the message	*/
  debug ("sending message...\n");
  net_write (conn, buf, strlen (buf));
  net_write (conn, content, strlen (content));
  debug ("reading response...\n");
  b = ebxml_receive (conn);
  debug ("closing socket...\n");
  net_close (conn);
  				/* no reply?			*/
  if (b == NULL)
  {
    warn ("Send response timed out or closed for %s\n", rname);

retrysend:			/* retry with a wait, or..	*/	
			
    if (retry-- && phineas_running ())
    {
      if (delay)
      {
	info ("Retrying send to %s in %d seconds\n", rname, delay);
        sleep (delay * 1000);
	delay <<= 1;
      }
      else			/* reset connection delay	*/
        delay = cfg_delay (xml);
      goto sendmsg;
    }
    if (ctx != NULL)		/* give up!			*/
      SSL_CTX_free (ctx);
    free (content);
    queue_field_set (r, "PROCESSINGSTATUS", "done");
    queue_field_set (r, "TRANSPORTSTATUS", "failed");
    queue_field_set (r, "TRANSPORTERRORCODE", "retries exhausted");
    return (-1);
  }
  debug ("reply was %d bytes\n%.*s\n", dbuf_size (b),
    dbuf_size (b), dbuf_getbuf (b));

  /*
   * handle redirects...
   * note this assumes the same SSL context should be used
   */
  if (ebxml_redirect (dbuf_getbuf (b), host, &port, path))
  {
    dbuf_free (b);
    goto sendmsg;
  }

  if (ctx != NULL)
    SSL_CTX_free (ctx);
  if (ebxml_parse_reply (dbuf_getbuf (b), r))
  {
    queue_field_set (r, "PROCESSINGSTATUS", "done");
    queue_field_set (r, "TRANSPORTSTATUS", "failed");
    queue_field_set (r, "TRANSPORTERRORCODE", "garbled reply");
  }
  debug ("send completed\n");
  dbuf_free (b);
  free (content);
  return (0);
}