Exemple #1
0
static enum proxy_status socks4a_connect(struct host *h,
 const char *target_host, int target_port)
{
  char handshake[8];
  int rBuf;
  target_port = platform_htons(target_port);

  _raw_host_connect(h, conf->socks_host, conf->socks_port);

  if (!__send(h, "\4\1", 2))
    return PROXY_SEND_ERROR;
  if (!__send(h, &target_port, 2))
    return PROXY_SEND_ERROR;
  if (!__send(h, "\0\0\0\1anonymous", 14))
    return PROXY_SEND_ERROR;
  if (!__send(h, target_host, strlen(target_host)))
    return PROXY_SEND_ERROR;
  if (!__send(h, "\0", 1))
    return PROXY_SEND_ERROR;

  rBuf = __recv(h, handshake, 8);
  if (rBuf == -1)
    return PROXY_CONNECTION_FAILED;
  if (handshake[1] != 90)
    return PROXY_HANDSHAKE_FAILED;
  return PROXY_SUCCESS;
}
Exemple #2
0
static enum proxy_status socks5_connect(struct host *h,
 struct addrinfo *ai_data)
{
  /* This handshake is more complicated than SOCKS4 or 4a...
   * and we're also only supporting none or user/password auth.
   */

  char handshake[10];
  int rBuf;

  _raw_host_connect(h, conf->socks_host, conf->socks_port);

  // Version[0x05]|Number of auth methods|auth methods
  if (!__send(h, "\5\1\0", 3))
    return PROXY_SEND_ERROR;

  rBuf = __recv(h, handshake, 2);
  if (rBuf == -1)
    return PROXY_CONNECTION_FAILED;
  if (handshake[0] != 0x5)
    return PROXY_HANDSHAKE_FAILED;

#ifdef CONFIG_IPV6
  if (ai_data->ai_family == AF_INET6)
    return PROXY_ADDRESS_TYPE_UNSUPPORTED;
#endif

  // Version[0x05]|Command|0x00|address type|destination|port
  if (!__send(h, "\5\1\0\1", 4))
    return PROXY_SEND_ERROR;
  if (!__send(h, ai_data->ai_addr->sa_data+2, 4))
    return PROXY_SEND_ERROR;
  if (!__send(h, ai_data->ai_addr->sa_data, 2))
    return PROXY_SEND_ERROR;

  rBuf = __recv(h, handshake, 10);
  if (rBuf == -1)
    return PROXY_CONNECTION_FAILED;
  switch (handshake[1])
  {
    case 0x0:
      return PROXY_SUCCESS;
    case 0x1:
    case 0x7:
      return PROXY_UNKNOWN_ERROR;
    case 0x2:
      return PROXY_ACCESS_DENIED;
    case 0x3:
    case 0x4:
    case 0x6:
      return PROXY_REFLECTION_FAILED;
    case 0x5:
      return PROXY_TARGET_REFUSED;
    case 0x8:
      return PROXY_ADDRESS_TYPE_UNSUPPORTED;
    default:
      return PROXY_UNKNOWN_ERROR;
  }
}
bool_ CTransaction::handlePushMessage(ub1_ ornType, ub8_ ornId, ub8_ ornExtId,
		ub8_ messageId, const c1_ *json, ub2_ size, ub8_ timestamp) {
	Message::TPDUPushMsg msg;

	msg.header.size = sizeof(Message::TPDUPushMsg);
	msg.header.type = Message::MT_SERVICE;
	msg.header.cmd = Message::MC_PUSH_MSG;
	msg.header.ver = Config::App::PROTOCOL_VERSION;
	msg.header.lang = Message::ML_CN;
	msg.header.seq = 0;
	msg.header.stmp = CBase::now();
	msg.header.ext = 0;
	msg.ornType = ornType;
	msg.ornId = ornId;
	msg.ornExtId = ornExtId;
	msg.messageId = messageId;
	memset(msg.json, 0, Size::JSON);
	assert(Length::JSON >= size);
	strncpy(msg.json, json, Length::JSON);

	bool_ ret = __send((Message::TMsg *) &msg, true_v);

	if (true_v == ret) {
		_lastUpdate = timestamp;
	}

	return ret;
}
// Called by CNodeGroup thread
bool_ CTransaction::__onSendMsg(const Message::TPDUSendMsg *msg) {
	log_debug("[%p]CTransaction::onSendMsg: current status-%d", this, _status);

	if (ETransactionStatus::READY != _status) {
		return over(ETransactionExitReason::WRONG_STATUS);
	}

	Message::TPDUSendMsgAck msgAck;

	memcpy(&msgAck.header, &msg->header, sizeof(Message::THeader));
	msgAck.header.size = sizeof(Message::TPDUSendMsgAck);
	msgAck.header.type |= Message::MT_SIGN_ACK;
	msgAck.header.stmp = CBase::now();
	msgAck.ack.code = 0;

	if (false_v
			== _node->getGroup()->ro().sendMessage(this, msg,
					msgAck.messageId)) {
		msgAck.ack.code = (ub2_)ETransactionExitReason::NO_DESTINATION_FOUND;
	}

	__send((Message::TMsg *) &msgAck, false_v);

	return true_v;
}
Exemple #5
0
static ssize_t http_send_line(struct host *h, const char *message)
{
  char line[LINE_BUF_LEN];
  ssize_t len;

  snprintf(line, LINE_BUF_LEN, "%s\r\n", message);
  len = (ssize_t)strlen(line);

  if(!__send(h, line, len))
    len = -HOST_SEND_FAILED;

  return len;
}
Exemple #6
0
static enum proxy_status socks4_connect(struct host *h,
 struct addrinfo *ai_data)
{
  char handshake[8];
  int rBuf;

  _raw_host_connect(h, conf->socks_host, conf->socks_port);

  if (!__send(h, "\4\1", 2))
    return PROXY_SEND_ERROR;
  if (!__send(h, ai_data->ai_addr->sa_data, 6))
    return PROXY_SEND_ERROR;
  if (!__send(h, "anonymous\0", 10))
    return PROXY_SEND_ERROR;

  rBuf = __recv(h, handshake, 8);
  if (rBuf == -1)
    return PROXY_CONNECTION_FAILED;
  if (handshake[1] != 90)
    return PROXY_HANDSHAKE_FAILED;
  return PROXY_SUCCESS;
}
Exemple #7
0
int __get_product(product_name name, Product * productp){
	char toSend[sizeof(product_name_msg)];
	msg_type resp_type;
	char resp_body[sizeof(product_resp)];
	
	__connect();
	msg_serialize_product_name_msg(__get_id(), GET_PRODUCT, name, toSend);
	__send(toSend, sizeof(product_name_msg));
	__recv(&resp_type, sizeof(msg_type));

	if (resp_type == OK_RESP) {
		__recv(resp_body, sizeof(Product));
		msg_deserialize_product(resp_body, productp);
		__disconnect();
		return OK;
	}
	return __handle_not_ok_resp(resp_type);
}
Exemple #8
0
int __write_product(product_name name, int quantity){
	char toSend[sizeof(product_msg)];
	msg_type resp_type;
	char resp_body[sizeof(error_resp)];
	int code;

	__connect();	
	msg_serialize_product_msg(__get_id(), WRITE_PRODUCT, product_new(name, quantity), toSend);
	__send(toSend, sizeof(product_msg));
	__recv(&resp_type, sizeof(msg_type));
	if (resp_type == OK_RESP) {
		__recv(resp_body, sizeof(int));
		msg_deserialize_code(resp_body, &code);
		__disconnect();
		return OK;
	}
	return __handle_not_ok_resp(resp_type);
}
Exemple #9
0
void
__vsyslog_chk(int pri, int flag, const char *fmt, va_list ap)
{
    struct tm now_tm;
    time_t now;
    int fd;
    FILE *f;
    char *buf = 0;
    size_t bufsize = 0;
    size_t msgoff;
#ifndef NO_SIGPIPE
    struct sigaction action, oldaction;
    int sigpipe;
#endif
    int saved_errno = errno;
    char failbuf[3 * sizeof (pid_t) + sizeof "out of memory []"];

#define	INTERNALLOG	LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
    /* Check for invalid bits. */
    if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) {
        syslog(INTERNALLOG,
               "syslog: unknown facility/priority: %x", pri);
        pri &= LOG_PRIMASK|LOG_FACMASK;
    }

    /* Check priority against setlogmask values. */
    if ((LOG_MASK (LOG_PRI (pri)) & LogMask) == 0)
        return;

    /* Set default facility if none specified. */
    if ((pri & LOG_FACMASK) == 0)
        pri |= LogFacility;

    /* Build the message in a memory-buffer stream.  */
    f = __open_memstream (&buf, &bufsize);
    if (f == NULL)
    {
        /* We cannot get a stream.  There is not much we can do but
           emitting an error messages.  */
        char numbuf[3 * sizeof (pid_t)];
        char *nump;
        char *endp = __stpcpy (failbuf, "out of memory [");
        pid_t pid = __getpid ();

        nump = numbuf + sizeof (numbuf);
        /* The PID can never be zero.  */
        do
            *--nump = '0' + pid % 10;
        while ((pid /= 10) != 0);

        endp = __mempcpy (endp, nump, (numbuf + sizeof (numbuf)) - nump);
        *endp++ = ']';
        *endp = '\0';
        buf = failbuf;
        bufsize = endp - failbuf;
        msgoff = 0;
    }
    else
    {
        __fsetlocking (f, FSETLOCKING_BYCALLER);
        fprintf (f, "<%d>", pri);
        (void) time (&now);
        f->_IO_write_ptr += __strftime_l (f->_IO_write_ptr,
                                          f->_IO_write_end
                                          - f->_IO_write_ptr,
                                          "%h %e %T ",
                                          __localtime_r (&now, &now_tm),
                                          _nl_C_locobj_ptr);
        msgoff = ftell (f);
        if (LogTag == NULL)
            LogTag = __progname;
        if (LogTag != NULL)
            __fputs_unlocked (LogTag, f);
        if (LogStat & LOG_PID)
            fprintf (f, "[%d]", (int) __getpid ());
        if (LogTag != NULL)
        {
            putc_unlocked (':', f);
            putc_unlocked (' ', f);
        }

        /* Restore errno for %m format.  */
        __set_errno (saved_errno);

        /* We have the header.  Print the user's format into the
               buffer.  */
        if (flag == -1)
            vfprintf (f, fmt, ap);
        else
            __vfprintf_chk (f, flag, fmt, ap);

        /* Close the memory stream; this will finalize the data
           into a malloc'd buffer in BUF.  */
        fclose (f);
    }

    /* Output to stderr if requested. */
    if (LogStat & LOG_PERROR) {
        struct iovec iov[2];
        struct iovec *v = iov;

        v->iov_base = buf + msgoff;
        v->iov_len = bufsize - msgoff;
        /* Append a newline if necessary.  */
        if (buf[bufsize - 1] != '\n')
        {
            ++v;
            v->iov_base = (char *) "\n";
            v->iov_len = 1;
        }

        __libc_cleanup_push (free, buf == failbuf ? NULL : buf);

        /* writev is a cancellation point.  */
        (void)__writev(STDERR_FILENO, iov, v - iov + 1);

        __libc_cleanup_pop (0);
    }

    /* Prepare for multiple users.  We have to take care: open and
       write are cancellation points.  */
    struct cleanup_arg clarg;
    clarg.buf = buf;
    clarg.oldaction = NULL;
    __libc_cleanup_push (cancel_handler, &clarg);
    __libc_lock_lock (syslog_lock);

#ifndef NO_SIGPIPE
    /* Prepare for a broken connection.  */
    memset (&action, 0, sizeof (action));
    action.sa_handler = sigpipe_handler;
    sigemptyset (&action.sa_mask);
    sigpipe = __sigaction (SIGPIPE, &action, &oldaction);
    if (sigpipe == 0)
        clarg.oldaction = &oldaction;
#endif

    /* Get connected, output the message to the local logger. */
    if (!connected)
        openlog_internal(LogTag, LogStat | LOG_NDELAY, 0);

    /* If we have a SOCK_STREAM connection, also send ASCII NUL as
       a record terminator.  */
    if (LogType == SOCK_STREAM)
        ++bufsize;

    if (!connected || __send(LogFile, buf, bufsize, send_flags) < 0)
    {
        if (connected)
        {
            /* Try to reopen the syslog connection.  Maybe it went
               down.  */
            closelog_internal ();
            openlog_internal(LogTag, LogStat | LOG_NDELAY, 0);
        }

        if (!connected || __send(LogFile, buf, bufsize, send_flags) < 0)
        {
            closelog_internal ();	/* attempt re-open next time */
            /*
             * Output the message to the console; don't worry
             * about blocking, if console blocks everything will.
             * Make sure the error reported is the one from the
             * syslogd failure.
             */
            if (LogStat & LOG_CONS &&
                    (fd = __open(_PATH_CONSOLE, O_WRONLY|O_NOCTTY, 0)) >= 0)
            {
                __dprintf (fd, "%s\r\n", buf + msgoff);
                (void)__close(fd);
            }
        }
    }

#ifndef NO_SIGPIPE
    if (sigpipe == 0)
        __sigaction (SIGPIPE, &oldaction, (struct sigaction *) NULL);
#endif

    /* End of critical section.  */
    __libc_cleanup_pop (0);
    __libc_lock_unlock (syslog_lock);

    if (buf != failbuf)
        free (buf);
}
Exemple #10
0
bool_ CTransaction::__onTimer(const Message::TPDUOnTimer *msg) {
	if (_keepLiveTimerId == msg->timerId) {
		if (_status != (ETransactionStatus)msg->parameter) {
			log_debug("[%p]CTransaction::onTimer: timer status(%d) != "
					"current(%d) status", this, msg->parameter, _status);

			return true_v;
		}

		if (ETransactionStatus::CONNECTED == _status) {
			log_debug("[%p]CTransaction::onTimer: waiting handshake timeout, "
					"current status-%d", this, _status);

			return over(ETransactionExitReason::TIME_OUT);
		} else if (ETransactionStatus::READY == _status) {
			if (false_v == _heartbeat) {
				log_debug("[%p]CTransaction::onTimer: heartbeat timeout, "
						"current status-%d", this, _status);

				return over(ETransactionExitReason::TIME_OUT);
			} else {
				Message::TPDUHeartBeat message;

				message.header.size = sizeof(Message::TPDUHeartBeat);
				message.header.type = Message::MT_CONTROL;
				message.header.cmd = Message::MC_HEART_BEAT;
				message.header.ver = Config::App::PROTOCOL_VERSION;
				message.header.lang = 1;
				message.header.seq = 0;

				__send((Message::TMsg *) &message, false_v);
				_heartbeat = false_v;
			}
		} else {
			assert(false_v);
		}

	} else {
		if (ETransactionStatus::READY != _status) {
			log_debug("[%p]CTransaction::onTimer: seq(%u)'s status(%d) is "
					"expected, but now it's status(%d)", this, msg->parameter,
					ETransactionStatus::READY, _status);

			return true_v;
		}

		ub4_ seq = (ub4_) msg->parameter;
		MapSeq2Timer::iterator pos = _mapSeq2Timer.find(seq);

		if (_mapSeq2Timer.end() != pos) {
			log_debug("[%p]CTransaction::onTimer: waitting ack timeout, "
					"current status-%d, seq-%u", this, _status, seq);

			return over(ETransactionExitReason::TIME_OUT);
		} else {
			assert(false_v);
		}
	}

	return true_v;
}
Exemple #11
0
bool_ CTransaction::__onStart(const Message::TPDUHandShake* msg) {
	log_debug("[%p]CTransaction::onStart: current status-%d", this, _status);

	if (ETransactionStatus::CONNECTED != _status) {
		return over(ETransactionExitReason::WRONG_STATUS);
	}

	assert(_keepLiveTimerId);
	CTransactionManager::instance()->killTimer(_keepLiveTimerId);
	_keepLiveTimerId = 0;

	Message::TPDUHandShakeAck msgAck;

	memcpy(&msgAck, msg, sizeof(Message::THeader));
	msgAck.header.size = sizeof(Message::TPDUHandShakeAck);
	msgAck.header.type |= Message::MT_SIGN_ACK;
	msgAck.ack.code = 0;

	if (Config::App::BASE_BUILD > msg->build) {
		log_notice("[%p]CTransaction::onStart: client version with %u or above"
				" is necessary, now it's %u", this, Config::App::BASE_BUILD,
				msg->build);
		msgAck.ack.code = (ub2_)ETransactionExitReason::CLIENT_TOO_OLD;
		__send((Message::TMsg *) &msgAck, false_v);

		return over(ETransactionExitReason::CLIENT_TOO_OLD);
	}

	memcpy(_sessionId, msg->sessionId, Size::SESSION_ID);
	_id = _node->getGroup()->ro().verifyHandshake(_sessionId);

	if (0 == _id) {
		log_notice("[%p]CTransaction::onStart: cannot find corresponding "
				"sessionId-%s", this, _sessionId);
		memset(_sessionId, 0, Size::SESSION_ID);
		_id = 0;
		msgAck.ack.code = (ub2_)ETransactionExitReason::NO_THE_SESSION_FOUND;
		__send((Message::TMsg *) &msgAck, false_v);

		return over(ETransactionExitReason::NO_THE_SESSION_FOUND);
	}

	if (false_v == CTransactionManager::instance()->registerTransaction(this)) {
		log_notice("[%p]CTransaction::onStart: there is an transaction with "
				"the same sessionId-%s and id-%lu", this, _sessionId, _id);
		memset(_sessionId, 0, Size::SESSION_ID);
		_id = 0;
		msgAck.ack.code = (ub2_)ETransactionExitReason::SAME_SESSION_ID;
		__send((Message::TMsg *) &msgAck, false_v);

		return over(ETransactionExitReason::SAME_SESSION_ID);
	}

	_status = ETransactionStatus::READY;
	msgAck.ack.code = 0;
	_lastUpdate = msg->lastUpdate;

	if (true_v == __send((Message::TMsg *) &msgAck, false_v)) {
		_heartbeat = true_v;
		_keepLiveTimerId = CTransactionManager::instance()->setTimer(
				Config::App::HEARTBEAT_INTERVAL, this, (obj_) _status, 0);

		if (0 == _keepLiveTimerId) {
			return over(ETransactionExitReason::NO_MORE_TIMER);
		}
	}

	return true_v;
}
Exemple #12
0
boolean host_handle_http_request(struct host *h)
{
  const char *mime_type = "application/octet-stream";
  char buffer[LINE_BUF_LEN], *buf = buffer;
  char *cmd_type, *path, *proto;
  enum host_status ret;
  size_t path_len;
  FILE *f;

  if(http_recv_line(h, buffer, LINE_BUF_LEN) < 0)
  {
    warn("Failed to receive HTTP request\n");
    return false;
  }

  cmd_type = strsep(&buf, " ");
  if(!cmd_type)
    return false;

  if(strcmp(cmd_type, "GET") != 0)
    return false;

  path = strsep(&buf, " ");
  if(!path)
    return false;

  proto = strsep(&buf, " ");
  if(!proto)
    return false;

  if(strncmp("HTTP/1.1", proto, 8) != 0)
  {
    warn("Client must support HTTP 1.1, rejecting\n");
    return false;
  }

  if(!http_skip_headers(h))
  {
    warn("Failed to skip HTTP headers\n");
    return false;
  }

  path++;
  debug("Received request for '%s'\n", path);

  f = fopen(path, "rb");
  if(!f)
  {
    warn("Failed to open file '%s', sending 404\n", path);

    snprintf(buffer, LINE_BUF_LEN,
     "HTTP/1.1 404 Not Found\r\n"
     "Content-Length: %zd\r\n"
     "Content-Type: text/html\r\n"
     "Connection: close\r\n\r\n", strlen(resp_404));

    if(__send(h, buffer, strlen(buffer)))
    {
      if(!__send(h, resp_404, strlen(resp_404)))
        warn("Failed to send 404 payload\n");
    }
    else
      warn("Failed to send 404 status code\n");

    return false;
  }

  path_len = strlen(path);
  if(path_len >= 4 && strcasecmp(&path[path_len - 4], ".txt") == 0)
    mime_type = "text/plain";

  ret = host_send_file(h, f, mime_type);
  if(ret != HOST_SUCCESS)
  {
    warn("Failed to send file '%s' over HTTP (error %d)\n", path, ret);
    return false;
  }

  return true;
}
Exemple #13
0
enum host_status host_send_file(struct host *h, FILE *file,
 const char *mime_type)
{
  boolean mid_deflate = false;
  char line[LINE_BUF_LEN];
  uint32_t crc, uSize;
  z_stream stream;
  long size;

  // Tell the client that we're going to use HTTP/1.1 features
  if(http_send_line(h, "HTTP/1.1 200 OK") < 0)
    return -HOST_SEND_FAILED;

  /* To bring ourselves into complete HTTP 1.1 compliance, send
   * some headers that we know our client doesn't actually need.
   */
  if(http_send_line(h, "Accept-Ranges: bytes") < 0)
    return -HOST_SEND_FAILED;
  if(http_send_line(h, "Vary: Accept-Encoding") < 0)
    return -HOST_SEND_FAILED;

  // Always zlib deflate content; keeps code simple
  if(http_send_line(h, "Content-Encoding: gzip") < 0)
    return -HOST_SEND_FAILED;

  // We'll just send everything chunked, unconditionally
  if(http_send_line(h, "Transfer-Encoding: chunked") < 0)
    return -HOST_SEND_FAILED;

  // Pass along a type hint for the client (mandatory sanity check for MZX)
  snprintf(line, LINE_BUF_LEN, "Content-Type: %s", mime_type);
  line[LINE_BUF_LEN - 1] = 0;
  if(http_send_line(h, line) < 0)
    return -HOST_SEND_FAILED;

  // Terminate the headers with a blank line
  if(http_send_line(h, "") < 0)
    return -HOST_SEND_FAILED;

  // Initialize CRC for GZIP footer
  crc = crc32(0L, Z_NULL, 0);

  // Record uncompressed size for GZIP footer
  size = ftell_and_rewind(file);
  uSize = (uint32_t)size;
  if(size < 0)
    return -HOST_FREAD_FAILED;

  while(true)
  {
    int deflate_offset = 0, ret = Z_OK, deflate_flag = Z_SYNC_FLUSH;
    char block[BLOCK_SIZE], zblock[BLOCK_SIZE];
    size_t block_size;

    /* Read a block from the disk source and compute a CRC32 on the
     * fly. This CRC will be dumped at the end of the deflated data
     * and is required for RFC 1952 compliancy.
     */
    block_size = fread(block, 1, BLOCK_SIZE, file);
    crc = crc32(crc, (Bytef *)block, block_size);

    /* The fread() above pretty much guarantees that block_size will
     * be BLOCK_SIZE up to the final block. However, fread() also
     * returns a short count if there was an I/O error, and we must
     * detect this. If it's legitimately the final block, give the
     * compressor this information.
     */
    if(block_size != BLOCK_SIZE)
    {
      if(!feof(file))
        return -HOST_FREAD_FAILED;
      deflate_flag = Z_FINISH;
    }

    /* We exhausted input at a block boundary. This is unlikely,
     * but in the event that it happens we can simply ignore
     * the deflate stage and write out the terminal chunk signature.
     */
    if(block_size == 0)
      break;

    /* Regardless of whether we are initializing the compressor in
     * the next section or not, we always have BLOCK_SIZE aligned
     * input data available.
     */
    stream.avail_in = block_size;
    stream.next_in = (Bytef *)block;

    if(!mid_deflate)
    {
      deflate_offset = zlib_forge_gzip_header(zblock);

      stream.avail_out = BLOCK_SIZE - (unsigned long)deflate_offset;
      stream.next_out = (Bytef *)&zblock[deflate_offset];
      stream.zalloc = Z_NULL;
      stream.zfree = Z_NULL;
      stream.opaque = Z_NULL;

      ret = deflateInit2(&stream, Z_BEST_COMPRESSION,
       Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
      if(ret != Z_OK)
        return -HOST_ZLIB_DEFLATE_FAILED;

      mid_deflate = true;
    }
    else
    {
      stream.avail_out = BLOCK_SIZE;
      stream.next_out = (Bytef *)zblock;
    }

    while(true)
    {
      unsigned long chunk_size;

      // Deflate a chunk of the input (partially or fully)
      ret = deflate(&stream, deflate_flag);
      if(ret != Z_OK && ret != Z_STREAM_END)
        return -HOST_ZLIB_INFLATE_FAILED;

      // Compute chunk length (final chunk includes GZIP footer)
      chunk_size = BLOCK_SIZE - stream.avail_out;
      if(ret == Z_STREAM_END)
        chunk_size += 2 * sizeof(uint32_t);

      // Dump compressed chunk length
      snprintf(line, LINE_BUF_LEN, "%lx", chunk_size);
      if(http_send_line(h, line) < 0)
        return -HOST_SEND_FAILED;

      // Send the compressed output block over the socket
      if(!__send(h, zblock, BLOCK_SIZE - stream.avail_out))
        return -HOST_SEND_FAILED;

      /* We might not have finished the entire stream, but the
       * available input is likely to have been exhausted. With
       * Z_SYNC_FLUSH this will commonly result in zero bytes
       * remaining in the input source. Additionally, if this is
       * the final chunk (and Z_FINISH was flagged), Z_STREAM_END
       * will be set. In either case, we must break out.
       */
      if((ret == Z_OK && stream.avail_in == 0) || ret == Z_STREAM_END)
        break;

      // Output has been flushed; start over for the remaining input (if any)
      stream.avail_out = BLOCK_SIZE;
      stream.next_out = (Bytef *)zblock;
    }

    /* Z_FINISH was flagged, stream ended
     * Terminate compression
     */
    if(ret == Z_STREAM_END)
    {
      // Free any zlib allocated resources
      deflateEnd(&stream);

      // Write out GZIP `CRC32' footer
      if(!__send(h, &crc, sizeof(uint32_t)))
        return -HOST_SEND_FAILED;

      // Write out GZIP `ISIZE' footer
      if(!__send(h, &uSize, sizeof(uint32_t)))
        return -HOST_SEND_FAILED;

      mid_deflate = false;
    }

    // Newline after chunk's data
    if(http_send_line(h, "") < 0)
      return -HOST_SEND_FAILED;

    // Final block; can break out
    if(block_size != BLOCK_SIZE)
      break;
  }

  // Terminal chunk signature, so called "trailer"
  if(http_send_line(h, "0") < 0)
    return -HOST_SEND_FAILED;

  // Post-trailer newline
  if(http_send_line(h, "") < 0)
    return -HOST_SEND_FAILED;

  return HOST_SUCCESS;
}
Exemple #14
0
boolean host_send_raw(struct host *h, const char *buffer, unsigned int len)
{
  return __send(h, buffer, len);
}
Exemple #15
0
static void
__vsyslogex_chk(int pri, int flag, pid_t cpid, pid_t ctid, const char *fmt, va_list ap) {
    struct tm now_tm;
    time_t now;
    int fd;
    FILE *f;
    char *buf = 0;
    size_t bufsize = 0;
    size_t prioff, msgoff;
#ifndef NO_SIGPIPE
    struct sigaction action, oldaction;
    int sigpipe;
#endif
    int saved_errno = errno;
    char failbuf[3 * sizeof (pid_t) + sizeof "out of memory []"];
    const int LogMask = setlogmask(0);

#ifdef _DEBUGFLAGS_H_
    {
        static unsigned int registered = 0;
        if (unlikely(0 == registered)) {
            registered = 1; /* dirty work around to avoid deadlock: syslogex->register->syslogex */
            registered = (registerLibraryDebugFlags(&debugFlags) == EXIT_SUCCESS);
        }
    }
#endif /*_DEBUGFLAGS_H_*/

#define INTERNALLOG LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
    /* Check for invalid bits. */
    if (unlikely(pri & ~(LOG_PRIMASK | LOG_FACMASK))) {
        /*syslog(INTERNALLOG,
               "syslog: unknown facility/priority: %x", pri);*/
        WARNING_MSG("unknown facility/priority: %x", pri);
        pri &= LOG_PRIMASK | LOG_FACMASK;
    }

    /* Check priority against setlogmask values. */
    if (unlikely((LOG_MASK(LOG_PRI(pri)) & LogMask) == 0))
        return;

    /* Set default facility if none specified. */
    if (unlikely((pri & LOG_FACMASK) == 0))
        pri |= LogFacility;

    /* Build the message in a memory-buffer stream.  */
    f = open_memstream(&buf, &bufsize);
    if (unlikely(f == NULL)) {
        /* We cannot get a stream.  There is not much we can do but
           emitting an error messages with the Process ID.  */
        char numbuf[3 * sizeof (pid_t)];
        char *nump;
        char *endp = __stpcpy(failbuf, "out of memory [");
        pid_t pid = getpid();

        nump = numbuf + sizeof (numbuf);
        /* The PID can never be zero.  */
        do {
            *--nump = '0' + pid % 10;
        } while ((pid /= 10) != 0);

        endp = mempcpy((void*) endp, (const void*) nump, (size_t) ((numbuf + sizeof (numbuf)) - nump));
        *endp++ = ']';
        *endp = '\0';
        buf = failbuf;
        bufsize = endp - failbuf;
        msgoff = 0;
    } else {
        __fsetlocking(f, FSETLOCKING_BYCALLER);
        prioff = fprintf(f, "<%d>", pri);
        (void) time(&now);
        f->_IO_write_ptr += strftime(f->_IO_write_ptr,
                f->_IO_write_end - f->_IO_write_ptr,
                "%h %e %T ",
                localtime_r(&now, &now_tm));
        /*f->_IO_write_ptr += strftime_l (f->_IO_write_ptr,
                                          f->_IO_write_end - f->_IO_write_ptr,
                                          "%h %e %T ",
                                          localtime_r (&now, &now_tm));*/
        msgoff = ftell(f);
        if (LogTag == NULL)
            LogTag = __progname;
        if (LogTag != NULL)
            fputs_unlocked(LogTag, f);
        if (LogStat & LOG_PID) {
            const pid_t pid = ((0 == cpid) ? getpid() : cpid);
            if (LogStat & LOG_TID) {
                const pid_t tid = ((0 == ctid) ? gettid() : ctid);
                fprintf(f, "[%d:%d]", (int) pid, (int) tid);
            } else {
                fprintf(f, "[%d]", (int) pid);
            }
        }

        if (LogStat & LOG_RDTSC) {
            const unsigned long long int t = rdtsc();
            fprintf(f, "(%llu)", t);
        } /* (LogStat & LOG_RDTSC) */

        if (LogStat & LOG_CLOCK) {
            #if HAVE_CLOCK_GETTIME
                struct timespec timeStamp;
                if (clock_gettime(CLOCK_MONOTONIC,&timeStamp) == 0) {
                    fprintf(f,"(%lu.%.9d)",timeStamp.tv_sec,timeStamp.tv_nsec);
                } else {
                    const int error = errno;
                    ERROR_MSG("clock_gettime CLOCK_MONOTONIC error %d (%m)",error);
            }
            #else
                static unsigned int alreadyPrinted = 0;
                if (unlikely(0 == alreadyPrinted)) {
                    ERROR_MSG("clock_gettime  not available on this system");
                    alreadyPrinted = 1;
                }
            #endif
        }  /* (LogStat & LOG_CLOCK) */

        if (LogStat & LOG_LEVEL) {
            switch (LOG_PRI(pri)) {
                case LOG_EMERG:
                    fprintf(f, "[EMERG]");
                    break;
                case LOG_ALERT:
                    fprintf(f, "[ALERT]");
                    break;
                case LOG_CRIT:
                    fprintf(f, "[CRIT]");
                    break;
                case LOG_ERR:
                    fprintf(f, "[ERROR]");
                    break;
                case LOG_WARNING:
                    fprintf(f, "[WARNING]");
                    break;
                case LOG_NOTICE:
                    fprintf(f, "[NOTICE]");
                    break;
                case LOG_INFO:
                    fprintf(f, "[INFO]");
                    break;
                case LOG_DEBUG:
                    fprintf(f, "[DEBUG]");
                    break;
            } /* switch(LOG_PRI(pri))*/
        } /* (LogStat & LOG_LEVEL) */

        if (LogTag != NULL) {
            putc_unlocked(':', f);
            putc_unlocked(' ', f);
        }

        /* Restore errno for %m format.  */
        __set_errno(saved_errno);

        /* We have the header.  Print the user's format into the
         buffer.  */
        if (flag == -1) {
            vfprintf(f, fmt, ap);
        } else {
            __vfprintf_chk(f, flag, fmt, ap);
        }

        /* Close the memory stream; this will finalize the data
           into a malloc'd buffer in BUF.  */
        fclose(f);
    }

    /* Output to stderr if requested. */
    if (LogStat & LOG_PERROR) {
        struct iovec iov[2];
        register struct iovec *v = iov;

        v->iov_base = buf + msgoff;
        v->iov_len = bufsize - msgoff;
        /* Append a newline if necessary.  */
        if (buf[bufsize - 1] != '\n') {
            ++v;
            v->iov_base = (char *) "\n";
            v->iov_len = 1;
        }

        pthread_cleanup_push(free, buf == failbuf ? NULL : buf);

        /* writev is a cancellation point.  */
        (void) writev(STDERR_FILENO, iov, v - iov + 1);

        pthread_cleanup_pop(0);
    }

    /* Prepare for multiple users.  We have to take care: open and
  write are cancellation points.  */
    struct cleanup_arg clarg;
    clarg.buf = buf;
    clarg.oldaction = NULL;
    pthread_cleanup_push(cancel_handler, &clarg);
    pthread_mutex_lock(&syslogex_lock);

#ifndef NO_SIGPIPE
    /* Prepare for a broken connection.  */
    memset(&action, 0, sizeof (action));
    action.sa_handler = sigpipe_handler;
    sigemptyset(&action.sa_mask);
    sigpipe = __sigaction(SIGPIPE, &action, &oldaction);
    if (sigpipe == 0)
        clarg.oldaction = &oldaction;
#endif

    /* Get connected, output the message to the local logger. */
    if (!connected) {
        openlog_internal(LogTag, LogStat | LOG_NDELAY, 0);
    }

    /* If we have a SOCK_STREAM connection, also send ASCII NUL as
  a record terminator.  */
    if (LogType == SOCK_STREAM) {
        ++bufsize;
    }

    if (!connected || __send(LogFile, buf, bufsize, send_flags) < 0) {
        if (connected) {
            /* Try to reopen the syslog connection.  Maybe it went
          down.  */
            closelog_internal();
            openlog_internal(LogTag, LogStat | LOG_NDELAY, 0);
        }

        if (!connected || __send(LogFile, buf, bufsize, send_flags) < 0) {
            closelog_internal(); /* attempt re-open next time */
            /*
             * Output the message to the console; don't worry
             * about blocking, if console blocks everything will.
             * Make sure the error reported is the one from the
             * syslogd failure.
             */
            if (LogStat & LOG_CONS &&
                    (fd = __open(_PATH_CONSOLE, O_WRONLY | O_NOCTTY, 0)) >= 0) {
                dprintf(fd, "%s\r\n", buf + msgoff);
                (void) __close(fd);
            }
        }
    }

#ifndef NO_SIGPIPE
    if (sigpipe == 0)
        __sigaction(SIGPIPE, &oldaction, (struct sigaction *) NULL);
#endif

    /* End of critical section.  */
    pthread_cleanup_pop(0);
    pthread_mutex_unlock(&syslogex_lock);

    if (buf != failbuf) {
        free(buf);
    }
}
Exemple #16
0
int
res_send(struct SocketBase *	libPtr,
	 const char *		buf,
	 int			buflen,
	 char *			answer,
	 int 			anslen)
{
	register int n;
	int try, v_circuit, resplen, nscount;
	int gotsomewhere = 0, connected = 0;
	int connreset = 0;
	u_short id, len;
	char *cp;
	fd_set dsmask;
	struct timeval timeout;
	struct in_addr *ns;
	struct sockaddr_in host;
	HEADER *hp = (HEADER *) buf;
	HEADER *anhp = (HEADER *) answer;
	u_char terrno = ETIMEDOUT;
#define JUNK_SIZE 512
	char junk[JUNK_SIZE]; /* buffer for trash data */

#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send()\n"));
D(bug("[AROSTCP](res_send.c) res_send: using socket %d\n", res_sock));
#endif

#ifdef RES_DEBUG
		printf("res_send()\n");
		__p_query(buf, libPtr);
#endif /* RES_DEBUG */

	v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
	id = hp->id;
	/*
	 * Send request, RETRY times, or until successful
	 */
	for (try = 0; try < _res.retry; try++) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Attempt %d\n", try));
#endif
	  nscount = 0;
	  DRES(Printf("Retry #%ld\n",try);)
	  for (ns = _res.nsaddr_list; ns->s_addr; ns++) {
	    nscount++;
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Querying server #%ld address = %s\n", nscount,
			      __inet_ntoa(ns->s_addr, libPtr)));
#endif

#ifdef RES_DEBUG
			Printf("Querying server #%ld address = %s\n", nscount,
			      __Inet_NtoA(ns->s_addr, libPtr));
#endif /* RES_DEBUG */
	    host.sin_len = sizeof(host);
	    host.sin_family = AF_INET;
	    host.sin_port = htons(NAMESERVER_PORT);
	    host.sin_addr.s_addr = ns->s_addr;
	    aligned_bzero_const(&host.sin_zero, sizeof(host.sin_zero));
	usevc:
		if (v_circuit) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Using v_circuit\n"));
#endif
			int truncated = 0;

			/*
			 * Use virtual circuit;
			 * at most one attempt per server.
			 */
			try = _res.retry;
			if (res_sock < 0) {
				res_sock = __socket(AF_INET, SOCK_STREAM, 0, libPtr);
				if (res_sock < 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Failed to create socket!!\n"));
					terrno = readErrnoValue(libPtr);
#endif
#ifdef RES_DEBUG
					    Perror("socket (vc)");
#endif /* RES_DEBUG */
					continue;
				}
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: created socket %d\n", res_sock));
#endif
				if (__connect(res_sock,
					    (struct sockaddr *)&host,
					    sizeof(struct sockaddr), libPtr) < 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Failed to connect\n"));
#endif
				        terrno = readErrnoValue(libPtr);
#ifdef RES_DEBUG
					    Perror("connect (vc)");
#endif /* RES_DEBUG */
					(void) __CloseSocket(res_sock, libPtr);
					res_sock = -1;
					continue;
				}
			}
			/*
			 * Send length & message
			 */
			len = htons((u_short)buflen);
			if ((__send(res_sock, (char *)&len, sizeof(len), 0, libPtr)
			     != sizeof(len)) ||
			   ((__send(res_sock, (char *)buf, buflen, 0, libPtr)
			     != buflen))) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Failed sending query\n"));
#endif
				terrno = readErrnoValue(libPtr);
#ifdef RES_DEBUG
					Perror("write(vc)");
#endif /* RES_DEBUG */
				(void) __CloseSocket(res_sock, libPtr);
				res_sock = -1;
				continue;
			}
			/*
			 * Receive length & response
			 */
			cp = answer;
			len = sizeof(short);
			while (len != 0 &&
			    (n = __recv(res_sock,
				      (char *)cp, (int)len, 0, libPtr)) > 0) {
				cp += n;
				len -= n;
			}
			if (n <= 0) {
				terrno = readErrnoValue(libPtr);
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Failed recieving response\n"));
#endif
#ifdef RES_DEBUG
					Perror("read (vc)");
#endif /* RES_DEBUG */
				(void) __CloseSocket(res_sock, libPtr);
				res_sock = -1;
				/*
				 * A long running process might get its TCP
				 * connection reset if the remote server was
				 * restarted.  Requery the server instead of
				 * trying a new one.  When there is only one
				 * server, this means that a query might work
				 * instead of failing.  We only allow one reset
				 * per query to prevent looping.
				 */
				if (terrno == ECONNRESET && !connreset) {
					connreset = 1;
					ns--;
				}
				continue;
			}
			cp = answer;
			if ((resplen = ntohs(*(u_short *)cp)) > anslen) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Truncated response\n"));
#endif
#ifdef RES_DEBUG
				       Printf("response truncated\n");
#endif /* RES_DEBUG */
				len = anslen;
				truncated = 1;
			} else
				len = resplen;
			while (len != 0 &&
			   (n = __recv(res_sock,
				     (char *)cp, (int)len, 0, libPtr)) > 0) {
				cp += n;
				len -= n;
			}
			if (n <= 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Error recieving response\n"));
#endif
				terrno = readErrnoValue(libPtr);
#ifdef RES_DEBUG
					Perror("read (vc)");
#endif /* RES_DEBUG */
				(void) __CloseSocket(res_sock, libPtr);
				res_sock = -1;
				continue;
			}
			if (truncated) {
				/*
				 * Flush rest of answer
				 * so connection stays in synch.
				 */
				anhp->tc = 1;
				len = resplen - anslen;
				while (len != 0) {
					n = (len > JUNK_SIZE ? JUNK_SIZE : len);
					if ((n = __recv(res_sock,
						      junk, n, 0, libPtr)) > 0)
						len -= n;
					else
						break;
				}
			}
		} else {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Using datagrams\n"));
#endif
			/*
			 * Use datagrams.
			 */
			if (res_sock < 0) {
				res_sock = __socket(AF_INET, SOCK_DGRAM, 0, libPtr);
				if (res_sock < 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Failed to create socket\n"));
#endif
					terrno = readErrnoValue(libPtr);
#ifdef RES_DEBUG
					    Perror("socket (dg)");
#endif /* RES_DEBUG */
					continue;
				}
			}
			/*
			 * I'm tired of answering this question, so:
			 * On a 4.3BSD+ machine (client and server,
			 * actually), sending to a nameserver datagram
			 * port with no nameserver will cause an
			 * ICMP port unreachable message to be returned.
			 * If our datagram socket is "connected" to the
			 * server, we get an ECONNREFUSED error on the next
			 * socket operation, and select returns if the
			 * error message is received.  We can thus detect
			 * the absence of a nameserver without timing out.
			 * If we have sent queries to at least two servers,
			 * however, we don't want to remain connected,
			 * as we wish to receive answers from the first
			 * server to respond.
			 */
#warning "TODO*: see comment here .."
			/* This piece of code still behaves slightly wrong in
			   case of ECONNREFUSED error. On next retry socket will
			   be in disconnected state and instead of getting
			   ECONNREFUSED again we'll timeout in WaitSelect() and
			   get ETIMEDOUT. However, this is not critical and is
			   queued for future - Pavel Fedin*/
			if (try == 0 && nscount == 1) {
				/*
				 * Don't use connect if we might
				 * still receive a response
				 * from another server.
				 */
				if (connected == 0) {
				  if (__connect(res_sock,
					      (struct sockaddr *)&host,
					      sizeof(struct sockaddr),
					      libPtr) < 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Error connecting\n"));
#endif
#ifdef RES_DEBUG
							Perror("connect (dg)");
#endif /* RES_DEBUG */
						continue;
					}
					connected = 1;
				}
				if (__send(res_sock,
					 buf, buflen, 0, libPtr) != buflen) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Error sending\n"));
#endif
#ifdef RES_DEBUG
						Perror("send (dg)");
#endif /* RES_DEBUG */
					continue;
				}
			} else {
				/*
				 * Disconnect if we want to listen
				 * for responses from more than one server.
				 */
				if (connected) {
					(void) __connect(res_sock, &no_addr,
					    sizeof(no_addr), libPtr);
					connected = 0;
				}
				if (__sendto(res_sock, buf, buflen, 0,
				    (struct sockaddr *)&host,
				    sizeof(struct sockaddr), libPtr) != buflen) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: [__sendto] Error\n"));
#endif
#ifdef RES_DEBUG
						Perror("sendto (dg)");
#endif /* RES_DEBUG */
					continue;
				}
			}

			/*
			 * Wait for reply
			 */
			timeout.tv_sec = (_res.retrans << try);
			if (try > 0)
				timeout.tv_sec /= nscount;
			if (timeout.tv_sec <= 0)
				timeout.tv_sec = 1;
			timeout.tv_usec = 0;
wait:
			FD_ZERO(&dsmask);
			FD_SET(res_sock, &dsmask);
			n = __WaitSelect(res_sock+1, &dsmask, NULL,
				NULL, &timeout, NULL, libPtr);
			if (n < 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: [__WaitSelect] Error\n"));
#endif
#ifdef RES_DEBUG
					Perror("select");
#endif /* RES_DEBUG */

            terrno = readErrnoValue(libPtr);
				if (terrno == EINTR) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: closing socket\n"));
#endif
					__CloseSocket(res_sock, libPtr);
					res_sock = -1;
					return (-1);
				}
				continue;
			}
			if (n == 0) {
				/*
				 * timeout
				 */
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Timeout!\n"));
#endif
#ifdef RES_DEBUG
					Printf("timeout\n");
#endif /* RES_DEBUG */
#if 1 || BSD >= 43
				gotsomewhere = 1;
#endif
				continue;
			}
			if ((resplen = __recv(res_sock,
					    answer, anslen, 0, libPtr)) <= 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Error recieving\n"));
#endif
#ifdef RES_DEBUG
					Perror("recv (dg)");
#endif /* RES_DEBUG */
				continue;
			}
			gotsomewhere = 1;
			if (id != anhp->id) {
				/*
				 * response from old query, ignore it
				 */
#ifdef RES_DEBUG
					Printf("old answer:\n");
					__p_query(answer, libPtr);
#endif /* RES_DEBUG */
				goto wait;
			}
			if (!(_res.options & RES_IGNTC) && anhp->tc) {
				/*
				 * get rest of answer;
				 * use TCP with same server.
				 */
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Response is truncated\n"));
#endif
#ifdef RES_DEBUG
					Printf("truncated answer\n");
#endif /* RES_DEBUG */
				(void)__CloseSocket(res_sock, libPtr);
				res_sock = -1;
				v_circuit = 1;
				goto usevc;
			}
		}

#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Recieved answer\n"));
#endif

#ifdef RES_DEBUG
			Printf("got answer:\n");
			__p_query(answer, libPtr);
#endif /* RES_DEBUG */
		/*
		 * If using virtual circuits, we assume that the first server
		 * is preferred * over the rest (i.e. it is on the local
		 * machine) and only keep that one open.
		 * If we have temporarily opened a virtual circuit,
		 * or if we haven't been asked to keep a socket open,
		 * close the socket.
		 */
		if ((v_circuit &&
		    ((_res.options & RES_USEVC) == 0 || ns->s_addr != 0)) ||
		    (_res.options & RES_STAYOPEN) == 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Closing socket\n"));
#endif
			(void) __CloseSocket(res_sock, libPtr);
			res_sock = -1;
		}
		return (resplen);
	   }