예제 #1
0
파일: mime.c 프로젝트: teapejon/phineas
/*
 * format a mime message - this is the recursive on, not intended
 * for external use.
 */
int mime_format_part (MIME *m, DBUF *b)
{
  MIME *n;
  char boundary[100];
  int bl;

  mime_size (m);
  dbuf_printf (b, "%s", m->headers);
  dbuf_write (b, m->body, m->len);
  if ((bl = mime_getBoundary (m, boundary, 100)) < 1)
    return (dbuf_size (b));
  boundary[bl++] = '\n';
  for (n = m->next; n != NULL; n = n->next)
  {
    debug ("adding next part at %d\n", dbuf_size (b));
    dbuf_write (b, boundary, bl);
    mime_format_part (n, b);
  }
  debug ("adding final boundary at %d\n", dbuf_size (b));
  dbuf_write (b, boundary, bl - 1);
  dbuf_write (b, "--\n", 4);
  debug ("final size is %d\n", dbuf_size (b));
  debug ("actual size is %d (%d/%d)\n",
      strlen (dbuf_getbuf(b)), strlen (m->headers), 
      strlen (dbuf_getbuf(b)) - strlen (m->headers));
  return (dbuf_size (b));
}
예제 #2
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);
}
예제 #3
0
파일: server.c 프로젝트: tdunnick/phineas
/*
 * TASK to handle an incoming request
 */
int server_request (void *parm)
{
  SERVERPARM *s;
  DBUF *req, *res;
  char *curl;

  s = (SERVERPARM *) parm;
  curl = xml_get_text (s->xml, "Phineas.Console.Url");
  res = NULL;
  while ((req = server_receive (s->conn)) != NULL)
  {
    debug ("received %d bytes\n", dbuf_size (req));
    if (dbuf_size (req) == 0)
    {
      dbuf_free (req);
      net_close (s->conn);
      return (-1);
    }
    dbuf_putc (req, 0);
    /*
     * log the request, but filter out GET requests for the console... 
     * noise
     */
    if (!(*curl && strstarts (dbuf_getbuf (req) + 4, curl)))
      server_logrequest (s->conn, dbuf_size (req), dbuf_getbuf (req));
    if ((res = server_response (s->xml, dbuf_getbuf (req))) == NULL)
    {
      res = server_respond (500,
	    "<h3>Failure processing ebXML request</h3>");
    }
    server_header (res);
    net_write (s->conn, dbuf_getbuf (res), dbuf_size (res));
    dbuf_free (res);
    dbuf_free (req);
  }
  net_close (s->conn);
  debug ("request completed\n");
  return (0);
}
예제 #4
0
파일: server.c 프로젝트: tdunnick/phineas
/*
 * set any needed header info
 */
int server_header (DBUF *b)
{
  char *ch,
       *status;
  int l,
      code = 200;
  char buf[120];

  /* find the end of the current header and get return code */
  if (strstarts (ch = dbuf_getbuf (b), "Status:"))
    code = atoi (ch + 8);
  l = 0;
  while (1)
  {
    if (l > dbuf_size (b) - 2)
    {
      l = 0;
      break;
    }
    if (ch[l++] != '\n')
      continue;
    if (ch[l] == '\r')
      l++;
    if (ch[l] == '\n')
      break;
    if (strstarts (ch + l, "Status:"))
      code = atoi (ch + l + 8);
  }
  if (code < 300)
    status = "OK";
  else if (code == 401)
    status = "Authorization Required";
  else if (code < 500)
    status = "NOT FOUND";
  else
    status = "SERVER ERROR";
  l = sprintf (buf, "HTTP/1.1 %d %s\r\n%s",
    code, status, l ? "" : "\r\n");
  debug ("inserting header %s", buf);
  dbuf_insert (b, 0, buf, l);
  return (0);
}
예제 #5
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);
}
예제 #6
0
/*
 * Receive a reply message
 */
DBUF *ebxml_receive (NETCON *conn)
{
  long n;
  int e;
  char c, *ch;
  DBUF *b;

  b = dbuf_alloc ();
  n = 0;
  /*
   * read to end of message request header - empty line
   */
  while ((e = net_read (conn, &c, 1)) == 1)
  {
    dbuf_putc (b, c);
    if (c == '\n')
    {
      if (n++ == 1)
        break;
    }
    else if (c != '\r')
      n = 0;
  }
  if (e != 1)
  {
    if (e == 0)
      error ("Acknowledgment header read failed or connection closed\n");
    else
      error ("Timed out reading acknowledgment header\n");
    dbuf_free (b);
    return (NULL);
  }
  ch = strnstr (dbuf_getbuf (b), "Content-Length: ", dbuf_size (b));
  if (ch == NULL)
  {
    error ("Acknowledgment header missing Content-Length\n");
    dbuf_free (b);
    return (NULL);
  }
  n = atol (ch + 16);
  debug ("expecting %d bytes\n", n);

readbytes:

  while (n--)
  {
    if ((e = net_read (conn, &c, 1)) != 1)
    {
      if (e == 0)
        error ("Acknowledgment content read failed or connection closed");
      else
        error ("Timed out reading acknowledgment content\n");
      // note we'll take what we get and hope it's enough...
      break;
    }
    dbuf_putc (b, c);
  }
  if (n = net_available (conn))
  {
    warn ("Found %d unread bytes...\n", n);
    goto readbytes;
  }
  debug ("returning %d bytes\n", dbuf_size (b));
  return (b);
}
예제 #7
0
파일: server.c 프로젝트: tdunnick/phineas
/*
 * Receive an incoming message
 */
DBUF *server_receive (NETCON *conn)
{
  long n, sz;
  char c, *ch;
  DBUF *b;

  b = dbuf_alloc ();
  n = 0;
  /*
   * read to end of message request header - empty line
   */
  while (net_read (conn, &c, 1) == 1)
  {
    dbuf_putc (b, c);
    if (c == '\n')
    {
      if (n++ == 1)
        break;
    }
    else if (c != '\r')
      n = 0;
  }
  if (n != 2)
  {
    debug ("no header - %d read\n", dbuf_size (b));
    if (dbuf_size (b))
    {
      dbuf_printf (b, "%s", n == 1 ? "\r\n" : "\r\n\r\n");
      warn ("can't find end of request header: %.*s", 
	dbuf_size (b), dbuf_getbuf (b));
    }
    n = 0;
  }
  else
  {
    ch = strnstr (dbuf_getbuf (b), "Content-Length: ", dbuf_size (b));
    if (ch == NULL)
      n = 0;
    else
      n = atol (ch + 16);
  }
  debug ("expecting %d bytes\n", n);

readbytes:

  while (n--)
  {
    if ((sz = net_read (conn, &c, 1)) != 1)
    {
      if (sz  == 0)
        error ("Read failed or connection closed\n");
      else
        error ("Read timed out\n");
      // note we'll take what we get and hope it's enough...
      break;
    }
    dbuf_putc (b, c);
  }
  if (n = net_available (conn))
  {
    warn ("Found %d unread bytes...\n", n);
    goto readbytes;
  }
  debug ("returning %d bytes\n", dbuf_size (b));
  return (b);
}