Exemplo n.º 1
0
static void handle_conn_read(struct conn *p_conn, struct pollfd *p_pollfd) {
  /* Log some debug info. */
  log_debug(NULL, "Reading connection %lu/socket %d (assigned pollfd %lu)",
      (unsigned long) p_conn->conn_idx,
      p_conn->sock,
      (unsigned long) p_conn->pollfd_idx);

  /* Parse the next portion of this client's request. */
  switch (parse_request(p_conn)) {
  case -1:
    /* If an error occurred, bail out. */
    handle_conn_delete(p_conn, p_pollfd);

  case 0:
    /* If no error occurred, but the request is not yet complete, try again
     * when there's more data to be read. */
    return;
  }

  /* Otherwise, no errors occurred and we got a complete selector. Now try to
   * serve the requested resource. */
  p_conn->stage = STAGE_RESPONSE_START;
  p_pollfd->events = POLLOUT;
  handle_conn_write(p_conn, p_pollfd);
}
Exemplo n.º 2
0
int main(int argc, char* argv[])
{
  const char* tmp;
  const char* end;
  int log_requests;
  
  log_requests = getenv("LOGREQUESTS") != 0;
  log_responses = getenv("LOGRESPONSES") != 0;

  tmp = getenv("TIMEOUT");
  if (tmp) {
    if ((timeout = strtou(tmp, &end)) == 0 || *end != 0) {
      respond(421, 1, "Configuration error, invalid timeout value");
      return 1;
    }
  }
  else
    timeout = 900;
  inbuf.io.timeout = timeout * 1000;
  outbuf.io.timeout = timeout * 1000;

  sig_alarm_catch(handle_alrm);
  if (!startup(argc, argv)) return 1;
  for (;;) {
    int len = read_request();
    if (len < 0) break;
    parse_request(len);
    if (!dispatch_request(internal_verbs, verbs, log_requests)) break;
  }
  return 0;
}
Exemplo n.º 3
0
int phr_parse_request(const char* buf_start, size_t len, const char** method,
		      size_t* method_len, const char** path, size_t* path_len,
		      int* minor_version, struct phr_header* headers,
		      size_t* num_headers, size_t last_len)
{
  const char * buf = buf_start, * buf_end = buf_start + len;
  size_t max_headers = *num_headers;
  int r;
  
  *method = NULL;
  *method_len = 0;
  *path = NULL;
  *path_len = 0;
  *minor_version = -1;
  *num_headers = 0;
  
  /* if last_len != 0, check if the request is complete (a fast countermeasure
     againt slowloris */
  if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) {
    return r;
  }
  
  if ((buf = parse_request(buf, buf_end, method, method_len, path, path_len,
			   minor_version, headers, num_headers, max_headers,
			   &r))
      == NULL) {
    return r;
  }
  
  return buf - buf_start;
}
Exemplo n.º 4
0
void dispatch_request(char* from, char* to, int accept_socket, int* keep_alive){
  char* req_str = (char*) malloc(sizeof(char) * (to - from + 1));
  char* char_i;
  int int_i;
  int _ = 0;
  for(char_i = from, int_i = 0; char_i < to; char_i++, int_i++){
    *(req_str + int_i) = *(char_i);
  }
  *(req_str + int_i) = '\0';
  struct request* req = malloc_request();
  parse_request(req, req_str);
  struct response* resp = malloc_response(req);
  //free(req_str);
  write_request(resp, accept_socket);
  if(resp->html == 0){
    read_file(req->resource_name, accept_socket);
  } else{
    _ = write(accept_socket, resp->html, strlen(resp->html));
    
  }
  if(_ == -1){
    printf("scream write %d\n", _);
  }
  *keep_alive = req->keep_alive;
  free(req_str);
  free_request(req);
  print_response(resp);
  free_response(resp); 
}
/**
 * Listening and handling incoming requests
 */
void HttpServer::listen()
{

    try
    {
        // Start server
        boost::asio::io_service io_service;
        tcp::endpoint localhost(tcp::v4(), this->port);
        tcp::acceptor acceptor(io_service, localhost);

        std::cout << "Server has started. Listening on address localhost:" << this->port 
            << " (that's 127.0.0.1:" << this->port << " for you Windows folks).\n\n"
            << "Now type this address into your browser." << std::endl;

        // Reply to incoming HTTP requests
        while (1)
        {
            boost::system::error_code error_code;
            
            // Accept connection
            tcp::socket socket(io_service);
            acceptor.accept(socket);

            // Send HTTP response
            std::string filepath = parse_request(socket, error_code);
            boost::asio::write(socket, boost::asio::buffer(build_response(filepath)), error_code);
        }
    }
    catch (std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }
}
Exemplo n.º 6
0
// Create a new cache object with a given maximum memory capacity.
cache_t create_cache(uint64_t maxmem){
    if (maxmem<1){
        fprintf(stderr,"400 Bad Request.\n");
        exit(2);
    }
    //Initialize cache
    cache_t cache = (cache_t) calloc(1, sizeof(struct cache_obj));
    assert(cache!=NULL&&"cache fails to allocate");
    char * servername = SERVERNAME_DF;
    char * servername_udp = SERVERNAME_DF;
    char * portnum = PORTNUM_DF;
    char * portnum_udp = PORTNUM_UDP_DF;
    char buffer[MAXDATASIZE];
    bzero(buffer,MAXDATASIZE);
    char content[REQUESTSIZE];
    bzero(content,REQUESTSIZE);
    
    cache->sockfd = initialize_TCP_client(servername, portnum);
    cache->sockfd_udp = initialize_UDP_client(servername_udp, portnum_udp);
    //resize cache to maxmem
    sprintf(content,"POST /memsize/%"PRIu64"",maxmem);
    parse_request(buffer,content,SERVERNAME_DF);
    if (write(cache->sockfd,buffer,strlen(buffer)) < 0) 
      {error("ERROR writing to socket");}
    bzero(buffer,MAXDATASIZE);
    if (read(cache->sockfd,buffer,MAXDATASIZE-1) < 0) 
      {error("ERROR reading from socket");}
    return cache;
}
Exemplo n.º 7
0
// Destroy all resource connected to a cache object
void destroy_cache(cache_t cache){
    if (cache==NULL){
        fprintf(stderr,"400 Bad Request.\n");
        exit(2);
    }

    char buffer[MAXDATASIZE];
    bzero(buffer,MAXDATASIZE);
    char content[REQUESTSIZE];
    bzero(content,REQUESTSIZE);
    sprintf(buffer,"POST /shutdown");
    parse_request(content,buffer,SERVERNAME_DF);

    if (write(cache->sockfd,content,strlen(content)) < 0) 
        {error("ERROR writing to socket");}
    bzero(buffer,MAXDATASIZE);
    if (read(cache->sockfd,buffer,MAXDATASIZE-1) < 0) 
        {error("ERROR reading from socket");}

    // UDP version
    // if (send(cache->sockfd_udp,buffer,strlen(buffer), 0) < 0) 
    // {error("ERROR sendto to socket");}
    // bzero(buffer,MAXDATASIZE);
    // if (recv(cache->sockfd_udp,buffer,MAXDATASIZE-1, 0 ) < 0) 
    //     {error("ERROR recvfrom from socket");}

    close(cache->sockfd);
    free(cache);
}
Exemplo n.º 8
0
// Compute the total amount of memory used up by all cache values (not keys)
uint32_t cache_space_used(cache_t cache){
    if (cache==NULL){
        fprintf(stderr,"400 Bad Request.\n");
        exit(2);
    }

    char buffer[MAXDATASIZE];
    bzero(buffer,MAXDATASIZE);
    char content[REQUESTSIZE];
    bzero(content,REQUESTSIZE);
    uint32_t space_use = 0;
    sprintf(buffer,"HEAD /0");
    parse_request(buffer,content,SERVERNAME_DF);

    if (write(cache->sockfd,buffer,strlen(buffer)) < 0) 
        {error("ERROR writing to socket");}
    bzero(buffer,MAXDATASIZE);
    if (read(cache->sockfd,buffer,MAXDATASIZE-1) < 0) 
        {error("ERROR reading from socket");}
    
    // UDP version
    // if (send(cache->sockfd_udp,buffer,strlen(buffer), 0) < 0) 
    // {error("ERROR sendto to socket");}
    // bzero(buffer,MAXDATASIZE);
    // if (recv(cache->sockfd_udp,buffer,MAXDATASIZE-1, 0 ) < 0) 
    //     {error("ERROR recvfrom from socket");}

  	get_spaceuse_from_head(buffer,&space_use);
  	return space_use;
}
Exemplo n.º 9
0
int
main(int argc, char **argv)
{
	char buffer[0x1000] = { 0 };
	char user[0x100], pwd[0x100], cookie[0x100] = { 0 };

	(void)(argc);
	(void)(argv);

	if (
		!getenv("REQUEST_METHOD") ||
		strcmp(getenv("REQUEST_METHOD"), "POST") ||
		!fread(buffer, 1, sizeof(buffer) - 1, stdin)
	)
		login_page(NULL);

	chomp(buffer);

	if (parse_request(buffer, user, sizeof(user), pwd, sizeof(pwd)))
		login_page("Missing username or password");

	if (!match_user("db/members.csv", user, pwd))
		login_page("Incorrect username or password");

	if (set_cookie("db/loggedin.csv", user, cookie, sizeof(cookie)))
		login_page("Internal error, please try again");

	catalog_page(user, cookie);
	return 0;
}
Exemplo n.º 10
0
// Add a <key, value> pair to the cache.
// If key already exists, it will overwrite the old value.
// If maxmem capacity is exceeded, sufficient values will be removed
// from the cache to accomodate the new value.
void cache_set(cache_t cache, key_type key, val_type val, uint32_t val_size){
    if (cache==NULL || key==NULL || val==NULL || val_size==0){
        fprintf(stderr,"400 Bad Request.\n");
        exit(2);
    }
    char buffer[MAXDATASIZE];
    bzero(buffer,MAXDATASIZE);
    char content[REQUESTSIZE];
    bzero(content,REQUESTSIZE);
    sprintf(content,"PUT /%s/%s",(char *)key,(char *)val);
    parse_request(buffer,content,SERVERNAME_DF);
    //printf("buffer:%s\n",buffer);
    if (write(cache->sockfd,buffer,strlen(buffer)) < 0) 
        {error("ERROR writing to socket");}

    bzero(buffer,MAXDATASIZE);
    if (read(cache->sockfd,buffer,MAXDATASIZE-1) < 0) 
        {error("ERROR reading from socket");}

    // UDP version
    // printf("buffer:%s\n",buffer);
    // if (send(cache->sockfd_udp,buffer,strlen(buffer), 0) < 0) 
    // {error("ERROR sendto to socket");}

    // bzero(buffer,MAXDATASIZE);
    // if (recv(cache->sockfd_udp,buffer,MAXDATASIZE-1, 0 ) < 0) 
    //     {error("ERROR recvfrom from socket");}
}
Exemplo n.º 11
0
// Process SER330 command
// This changes the serial number in seneca.config file
// then restarts the q330serv program to use the new serial number
void process_ser330()
{
 int64_t serno;
 int     count;
 char    cmdstr[80];
 fprintf(stderr, "Processing %s\n", incmdbuf);

 // Validate the serial number
 ++cmdcnt ;
 parse_request(' ') ;
 serno = 0 ;
 count = sscanf(prsbuf,"%Lx", &serno) ;
 if (count != 1)
 {
   send_data ("Unable to parse serial number\n") ;
   return;
 }

 // Use a shell script to make changes, restart q330serv
 sprintf(cmdstr, "newser330 %016Lx", serno);
 if (system(cmdstr) == -1)
 {
   if (gDebug)
     fprintf(stderr, "system(%s) returned error\n", cmdstr);
   else
     syslog(LOG_ERR, "system(%s) returned error\n", cmdstr);
   send_data ("newser330 command returned error, status unknown\n") ;
   return;
 }
 
} // process_ser330()
Exemplo n.º 12
0
void route (WiFiClient socket, Router *router, uint8_t *req) {
#else
void route (uint8_t socket, Router *router, uint8_t *req) {
#endif
  Request *request;
  Response *response;

  request = parse_request(req);
  response = response_create(socket);

  if (router->write) {
    response->write = router->write;
  }

  if (request->method == HTTP_ERROR) {
    five_hundred(request, response);
  } else {
    int8_t found = find_route(router, request->path);

    if (found != -1) {
      router->routes[found].method(request, response);
    } else {
      four_oh_four(request, response);
    }
  }
}
Exemplo n.º 13
0
void replay_thread(void *fd) {
	int c_sock = (int)fd;
	char in_buf[MAXDATA];
	char out_buf[MAXDATA];
	int size;

	// TODO
	/*while(1) {
		memset(in_buf, 0, sizeof(in_buf));
		size = 0;
		size = read(c_sock, in_buf, sizeof(in_buf));
		if (size == 0) {
			break;
		} else if (size == -1) {
			perror("read");
			exit(EXIT_FAILURE);
		} else {
			parse_request(in_buf);
		}
	}*/

	memset(in_buf, 0, sizeof(in_buf));
	size = read(c_sock, in_buf, sizeof(in_buf));
	parse_request(in_buf);

	memset(out_buf, 0, sizeof(out_buf));
	create_response(out_buf, sizeof(out_buf));
	write(c_sock, out_buf, sizeof(out_buf));

	if ( close(c_sock) < 0) {
		perror("close");
		exit(EXIT_FAILURE);
	}
	printf("Thread Connection closed.\n");
}
Exemplo n.º 14
0
/*
@details
-# Loop until the connection is broken or timed_out
 -# Call select to wait up to 15 seconds for a message.
 -# If a message is found, read it into the incoming_msg buffer
 -# Call parse_request on the incoming_msg buffer
-# Disconnect the socket connection
*/
void * Trick::JSONVariableServerThread::thread_body() {

    int nbytes = -1 ;
    socklen_t sock_size = sizeof(connection.remoteServAddr) ;
    fd_set rfds;
    struct timeval timeout_time = { 15, 0 };
    bool timed_out = false ;

    while (! timed_out and nbytes != 0 ) {
        FD_ZERO(&rfds);
        FD_SET(connection.socket, &rfds);
        timeout_time.tv_sec = 15 ;
        select(connection.socket + 1, &rfds, NULL, NULL, &timeout_time);

        if ( FD_ISSET(connection.socket, &rfds)) {
            nbytes = recvfrom( connection.socket, incoming_msg, MAX_CMD_LEN, 0 ,
                     (struct sockaddr *)&connection.remoteServAddr, &sock_size ) ;
            //std::cout << "nbytes = " << nbytes << std::endl ;
            if (nbytes != 0 ) {
                //std::cout << incoming_msg << std::endl ;
                parse_request() ;
            }
        } else {
            timed_out = true ;
        }
    }
    tc_disconnect(&connection) ;
    //std::cout << "closed variable server connection" << std::endl ;

    return NULL ;
}
Exemplo n.º 15
0
void server(void)
{
//	request re;
	int size = sizeof(re);

	int no = 0;
//	recv(new_sockfd, &re, size, 0);

	while(1) 
	{
		recv(new_sockfd, &req_body, 1000, 0);
		printf("%s\n", req_body);
//		parse_request(req_body);
		strcpy(res_body, "<h1> Hello </h1>");
		send_response(
			handle_request(
				parse_request(req_body)
			)
		);
		printf("%s", res_body);
		send(new_sockfd, &res_body, sizeof(res_body), 0);
//		shutdown(new_sockfd, SHUT_WR);
	//	return 0;
	}
	printf("NEW SOCKFD %d\n", new_sockfd);
	new_sockfd = 0;
}
Exemplo n.º 16
0
void serv_proc(int fd){
	char buf[MAXLINE];
	Req_header header;

	char delims[] = "/";
	char *result = NULL;

	readline(fd, buf, MAXLINE);
#ifdef DEBUG
	fprintf(stderr, "%s", buf);
#endif

	parse_request(buf, &header);

	
	memset(buf, 0, MAXLINE);
	strcpy(buf, header.locator);
	result = strtok(buf, delims);

	if (strcmp(result, "cgi-bin") == 0) {
		cgi_handle(fd, &header);
	} else {
		http_respond(fd, &header);
	}

	servlog(LOG_INFO, "[client:%s][%s] %d\n", "192.168.1.1", "GET /index.html HTTP/1.1", 200);

}
Exemplo n.º 17
0
/*
 * Process the request data.
 */
int processRequest(char *data, int length, struct http_param *param)
{
	int processed=0;
	char *p=NULL;

	/* Just go ahead and record how much data is here */
	processed=length;

	/* Don't do any of this stuff unless we don't have it yet */
	if(param->req==NULL) {
		/* Wait until we have enough headers */
		if( (p=strstr(data, "\r\n\r\n"))==NULL) {
			return(0);
		}

		*p=0x00;
		p++;
		if(strlen(p)>3) {
			while(*p && (*p=='\r' || *p=='\n')) { p++; }
			param->extra=strdup(p);
		}

		parse_request(data, param);

	}

	return(processed);
}
Exemplo n.º 18
0
int main()
{
	//FT_HANDLE fthandle=scan_device();
	//float t;
	//char entry[MAX_ENTRY];
	char *request=NULL;
	printf("Content-type: text/plain\n\n");
#if DEBUG
	request=get_request();
	parse_request(request);
#else
	request=get_request();
	parse_request(request);
#endif
	return 0;
}
Exemplo n.º 19
0
Arquivo: tasks.c Projeto: tgdiriba/os
void parse_request_task(void* arg)
{
  parse_request_arg* parse_task = (parse_request_arg*) arg;
  if (parse_task != NULL &&
      parse_task->pool != NULL &&
      parse_task->req != NULL) {
    if (parse_request(parse_task->connfd, parse_task->req)) {
      process_request_arg* process_task =
        (process_request_arg*) malloc(sizeof(process_request_arg));
      process_task->pool = parse_task->pool;
      process_task->connfd = parse_task->connfd;
      process_task->req = parse_task->req;
      clock_gettime(CLOCK_MONOTONIC_RAW, &process_task->start_time);

      // Add the process request task to the queue.
      pool_add_task(parse_task->pool, process_request_task, (void*)process_task);
    } else {
      if (parse_task != NULL) {
        free(parse_task->req);
      }
    }
  } else {
    if (parse_task != NULL) {
      free(parse_task->req);
    }
  }

  free(parse_task);
}
Exemplo n.º 20
0
static int parse_request_lua( lua_State *L )
{
    lhttp_t *h = luaL_checkudata( L, 1, MODULE_MT );
    size_t len = 0;
    char *buf = (char*)luaL_checklstring( L, 4, &len );

    return parse_request( L, h, buf, len );
}
Exemplo n.º 21
0
/**
 * Handles incoming data on a client connection.
 * @param socket_server Socket server
 * @param conn Client connection
 */
static void handle_connection(struct lwpb_transport_socket_server *socket_server,
        struct lwpb_socket_server_conn *conn)
{
    void *res_buf;
    size_t res_len;
    ssize_t len;
    size_t used;
    struct protocol_header_info info;
    lwpb_err_t ret;
    
    used = conn->pos - conn->buf;
    
    len = recv(conn->socket, conn->pos, conn->len - used, 0);
    if (len <= 0) {
        close_connection(socket_server, conn);
        return;
    }
    
    conn->pos += len;
    used = conn->pos - conn->buf;
    
    LWPB_DEBUG("Client(%d) received %d bytes", conn->index, len);
    
    // Try to decode the request
    ret = parse_request(conn->buf, used, &info, socket_server->server->service_list);
    if (ret != PARSE_ERR_OK)
        return;
    
    LWPB_DEBUG("Client(%d) received request header", conn->index);
    LWPB_DEBUG("type = %d, service = %p, method = %p, header_len = %d, msg_len = %d",
               info.msg_type, info.service_desc, info.method_desc,
               info.header_len, info.msg_len);
    
    if (!info.service_desc) {
        // TODO unknown service
    }
    
    if (!info.method_desc) {
        // TODO unknown method
    }
    
    // Allocate response buffer
    ret = lwpb_transport_alloc_buf(&socket_server->super, &res_buf, &res_len);
    if (ret != LWPB_ERR_OK) {
        // TODO handle memory error
    }
    
    ret = socket_server->server->call_handler(
        socket_server->server, info.method_desc,
        info.method_desc->req_desc,conn->buf + info.header_len, info.msg_len,
        info.method_desc->res_desc, res_buf, &res_len,
        socket_server->server->arg);
    
    // Send response back to server
    send_response(conn->socket, info.method_desc, res_buf, res_len);
    
    lwpb_transport_free_buf(&socket_server->super, res_buf);
}
Exemplo n.º 22
0
char *process_request(char *res, char *reqstr)
{
	Request reqobj = parse_request(reqstr);
	//res = process_action(res, reqobj);
	Response resobj = build_fake_response();
	res = response_obj_to_string(resobj);
	
	return res;
}
Exemplo n.º 23
0
Arquivo: bench.c Projeto: ifzz/libhttp
int main( int argc, const char *argv[] ) 
{
    printf("parse_request:\n");
    parse_request();
    printf("parse_response:\n");
    parse_response();
    
    return 0;
}
Exemplo n.º 24
0
 virtual int execute(Reader& reader, Writer& writer)
 {
     int result = parse_request(reader);
     if (!result) {
         result = process();
         produce_response(writer, result);
     }
     return result;
 }
Exemplo n.º 25
0
static int parse_request_ptr_lua( lua_State *L )
{
    lhttp_t *h = luaL_checkudata( L, 1, MODULE_MT );
    char *buf = (char*)lua_topointer( L, 4 );
    size_t len = luaL_checkinteger( L, 5 );


    return parse_request( L, h, buf, len );
}
Exemplo n.º 26
0
int init_request(REQUEST* req,USER_INFO* info,Uint32 action_code,char* enc_data,int size){
	req->user_id = info->user_id;
	req->action_code = action_code;
	req->info = info;
	req->enc_size = size;
	req->enc_data = enc_data;
	req->host = null;
	req->data = null;
	return (parse_request(req));
}
Exemplo n.º 27
0
void do_request(struct wen_request *request)
{
	if(!parse_request(request)){
		bad_request(request);
		wen_free(request);
		return ;
	}

	//wen_free(request);
}
Exemplo n.º 28
0
boolean RestServer::handle_requests(Stream &_client) {
	if (_client.available()) {
		start_timer();
		read_request(_client.read());
	}
	parse_request();
	process();	
	if (server_state == PROCESS) return true;
	else return false;
}
Exemplo n.º 29
0
//0:continue -1:error 1:finish
static int do_read(struct fd_state *state) {
    assert(state);
    char buf[1024];
    
    enum io_tatus status = s_error;
    while (1) {
        ssize_t nread = read(state->fd, buf, sizeof(buf));
        if (nread < 0) {
            if (errno == EAGAIN)
                status = s_ok;
            else
                status = s_error;
            break;
        }
        if (nread == 0) {
            status = s_disconnect;
            break;
        }
        if (nread <= sizeof(state->read_buf) - state->n_read -1) {
            memcpy(state->read_buf + state->n_read, buf, nread);
            state->n_read += nread;
            state->read_buf[state->n_read] = 0;
        } else {
            status = s_error;
            break;
        }
    }
    
    if (status == s_ok) {
        const char *endtoken = "\r\n\r\n";
        const char *httpend = strstr(state->read_buf, endtoken);
        if (httpend && httpend < state->read_buf + state->n_read) {
            parse_request(state);
            
            httpend += strlen(endtoken);
            size_t remain = state->read_buf + state->n_read - httpend;
            if (remain > 0) {
                memmove(state->read_buf, httpend, remain);
            }
            state->n_read = remain;
            state->is_writing = 1;
			
			struct epoll_event event;
			event.data.ptr = state;
			event.events = EPOLLIN | EPOLLOUT;
			int s = epoll_ctl(_epoll, EPOLL_CTL_MOD, state->fd, &event);
			if (s == -1){
				status = s_error;
				return status;
			}
        }
    }

    return status;
}
Exemplo n.º 30
0
static struct io_plan *read_json(struct io_conn *conn,
				 struct json_connection *jcon)
{
	jsmntok_t *toks;
	bool valid;

	log_io(jcon->log, true, jcon->buffer + jcon->used, jcon->len_read);

	/* Resize larger if we're full. */
	jcon->used += jcon->len_read;
	if (jcon->used == tal_count(jcon->buffer))
		tal_resize(&jcon->buffer, jcon->used * 2);

again:
	toks = json_parse_input(jcon->buffer, jcon->used, &valid);
	if (!toks) {
		if (!valid) {
			log_unusual(jcon->dstate->base_log,
				    "Invalid token in json input: '%.*s'",
				    (int)jcon->used, jcon->buffer);
			return io_close(conn);
		}
		/* We need more. */
		goto read_more;
	}

	/* Empty buffer? (eg. just whitespace). */
	if (tal_count(toks) == 1) {
		jcon->used = 0;
		goto read_more;
	}

	parse_request(jcon, toks);

	/* Remove first {}. */
	memmove(jcon->buffer, jcon->buffer + toks[0].end,
		tal_count(jcon->buffer) - toks[0].end);
	jcon->used -= toks[0].end;
	tal_free(toks);

	/* Need to wait for command to finish? */
	if (jcon->current) {
		jcon->len_read = 0;
		return io_wait(conn, jcon, read_json, jcon);
	}

	/* See if we can parse the rest. */
	goto again;

read_more:
	tal_free(toks);
	return io_read_partial(conn, jcon->buffer + jcon->used,
			       tal_count(jcon->buffer) - jcon->used,
			       &jcon->len_read, read_json, jcon);
}