1

EDIT After some more reading, the broken pipe error just means that I terminated the connection. But the question remains, why is the read request hanging?

I'm very new to this so please bear with me.

I've got a tiny webapp in flask running on localhost which looks like this:

import stuff
app = Flask(__name__)
...do some stuff
@app.route("/")
def foo():

    resp_OK = Response(response="", status=200)
    resp_NO = Response(response="", status=500)

    ...do some stuff

    if some stuff:
        return resp_NO
    else:
        return resp_OK

if __name__== '__main__':
    app.run()

if I just type the localhost:5000/?param1=therightparamts&param2=tomakeitwork, everything works fine, the command line response is either 200 or 500 accordingly.

Now, I'm trying to get this response from inside C, the code for which I borrowed from Jeremy Jeremiah's response here. As far as I can tell, it opens the socket and sends the request, and then it fails to read the response. I just want to know if the webapp returned 200 or 500. Here's the relevant bit of C code:

char response[4096];
int total, received, bytes;
...
sockfd = socket(AF_INET, SOCK_STREAM, 0);
...
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
    error("ERROR connecting");
...
do {
    bytes = write(sockfd,&(message.c[sent]),total-sent);
    ...}while(...);
...
memset(response,0,sizeof(response));
total = sizeof(response)-1;
received = 0;
do {
    bytes = read(sockfd,response+received,total-received);
    printf("Read %i bytes.\n", received); fflush(stdout);
    if (bytes < 0)
        error("ERROR reading response from socket");
    if (bytes == 0)
        break;
    received+=bytes;
} while (received < total);

It never gets to the printf after read(sockfd...). If I terminate the C program while it's hanging, the console output is

127.0.0.1 - - [27/Dec/2015 14:25:33] "GET /?file=foo&signature=46b4ec586117154dacd49d664e5d63fdc88efb51 HTTP/1.1" 500 -
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 2363)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 295, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 321, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 334, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python2.7/SocketServer.py", line 657, in __init__
    self.finish()
  File "/usr/lib/python2.7/SocketServer.py", line 716, in finish
    self.wfile.close()
  File "/usr/lib/python2.7/socket.py", line 283, in close
    self.flush()
  File "/usr/lib/python2.7/socket.py", line 307, in flush
    self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe
----------------------------------------

If I keyboard interrupt the webapp while the C program is hanging, the response is as follows:

Exception happened during processing of request from ('127.0.0.1', 3760)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 295, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 321, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 334, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python2.7/SocketServer.py", line 655, in __init__
    self.handle()
  File "/home/gmoss/.local/lib/python2.7/site-packages/werkzeug/serving.py", line 217, in handle
    rv = BaseHTTPRequestHandler.handle(self)
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 340, in handle
    self.handle_one_request()
  File "/home/gmoss/.local/lib/python2.7/site-packages/werkzeug/serving.py", line 251, in handle_one_request
    elif self.parse_request():
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 291, in parse_request
    self.headers = self.MessageClass(self.rfile, 0)
  File "/usr/lib/python2.7/mimetools.py", line 25, in __init__
    rfc822.Message.__init__(self, fp, seekable)
  File "/usr/lib/python2.7/rfc822.py", line 108, in __init__
    self.readheaders()
  File "/usr/lib/python2.7/rfc822.py", line 155, in readheaders
    line = self.fp.readline()
  File "/usr/lib/python2.7/socket.py", line 451, in readline
    data = self._sock.recv(self._rbufsize)
KeyboardInterrupt
----------------------------------------

I looked at some of the other answers on SO but don't quite understand how to apply those answers to my situation (as I said, new to this). Would appreciate any pointers in the right direction.

Community
  • 1
  • 1
gmoss
  • 1,019
  • 5
  • 17
  • 1
    just out of curiosity, why feed this into a c program? – wgwz Dec 27 '15 at 22:55
  • I wonder that myself sometimes... I'm doing the Matasano problems, I started doing them in C, so all the crypto utils I've implemented so far are in C. I thought about making the webapp in C too but thankfully I have some common sense left... – gmoss Dec 27 '15 at 22:58
  • 1
    just throwing it out there, if you haven't heard of cython, you should check it out. you can wrap c-libraries with it and then import into python. here's a nice intro, his book is good too (https://www.youtube.com/watch?v=gMvkiQ-gOW8&index=10&list=PLYx7XA2nY5Gcpabmu61kKcToLz0FapmHu) – wgwz Dec 27 '15 at 23:02
  • Thanks, I'll look into it! – gmoss Dec 27 '15 at 23:05
  • if the c-code is relatively short, it should be pretty easy to get up and running with cython. cython does optimizations on c-code, so what you get out of it, and import into python can often times run more efficiently. in that tutorial i linked it shows how to wrap a basic fib function. it's a fun tool, imo. – wgwz Dec 27 '15 at 23:14
  • glad to see you got it working. regarding cython again, functions that are imported from cython wrapped c-libraries are actually computed in c-speed and often times better. so you don't sacrifice speed by bringing your c code into python. – wgwz Dec 27 '15 at 23:47
  • I'll be sure to try it out soon! The current code for this project is pretty long, and I'm pretty happy with getting it working in C, but I do want to play with importing C code into python, as that sounds super useful. I'm pretty new to programming, I'm just finishing up my math degree and this is kind of a side project as I procrastinate on writing my dissertation :) – gmoss Dec 27 '15 at 23:52
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/99077/discussion-between-skywalker-and-gmoss). – wgwz Dec 28 '15 at 00:06

1 Answers1

1

Got it working by ditching the above approach and using cURL instead. (string, newString etc. are my own custom string utils).

int curlRequest(int argc, string *argv)
{
  CURL *curl;
  CURLcode res;
  string url;
  int i;
  long http_code;

  url=newString("http://localhost:5000",0);
  /* fill in the parameters */
  url=stringCat(url, newString("/?",0));
  for(i=0; i<argc; i++){
    url = stringCat(url, argv[i]);
    if(i+1<argc) url = stringCat(url, newString("&",0));
  }
  //url = stringCat(url, newString(" HTTP/1.1\r\n",0));


  curl = curl_easy_init();
  if(curl) {
    curl_easy_setopt(curl, CURLOPT_URL, url.c);

    /* Perform the request, res will get the return code */
    res = curl_easy_perform(curl);
    /* Check for errors */
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));
    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);

    /* always cleanup */
    curl_easy_cleanup(curl);
  }
  return http_code;
}
gmoss
  • 1,019
  • 5
  • 17