0

So I've been working on pset6 for a while now, the hardest thing with it is that it is very hard to test (I use a test.c file to do that and lots of printf functions), and the whole code of server.c is kind of confusing, I feel like I'm shooting in the dark sometimes.

Anyway, with that said, I think I completed "lookup" but cannot really test it as my code never gets there. When I run my code and try to go on the webpage I get 301 moved permanently, and on the page I get "too many redirects". From this I deduced that the problem must be with my abs_path and query pointers. A sad deduction because I spent days on doing parse.

Allow me to paste in my (most likely) faulty code and explain what I am trying to do with it:

bool parse(const char* line, char* abs_path, char* query)
{

// declaring arrays for holding all these strings (and feels)
char abpathholder[LimitRequestLine + 1];
char queryholder[LimitRequestLine + 1];
char httpholder[9];
memset(abpathholder, 0, LimitRequestLine + 1);
memset(queryholder, 0, LimitRequestLine + 1);
memset(httpholder, 0, 9);

// getting the start of absolut path and the start of HTTP version - 1  
char* abpathstart = strchr(line, '/');
char* lastspace = strrchr(line, ' ');
char* querystart = strchr(line, '?');

// setting up an int to see where the path and query ends
int pathend;
int queryend;

// checks if there is a query and sets difference in strings accordingly, also gets the query
if (querystart == NULL)
{
    pathend = strlen(abpathstart) - strlen(lastspace);
    queryholder[0] = '\0';
}
else
{
    pathend = strlen(abpathstart) - strlen(querystart);
    queryend = strlen(querystart) - strlen(lastspace) - 1;

    for ( int i = 0; i < queryend; i++)
    {
        queryholder[i] = querystart[i + 1];
    }
}

// copies accurate number of chars for abpath
for (int i = 0; i < pathend; i++)
{
    abpathholder[i] = abpathstart[i];
}

//for (int i = 0; i < strlen(abpathholder); i++)
//    printf("This is in abpathholder: %c\n", abpathholder[i]);


for (int i = 1; i < strlen(lastspace); i++)
{
    if (lastspace[i] == '\r')
    {
        break;
    }
    else
    {
        httpholder[i - 1] = lastspace[i];
    }
}

//for (int i = 0; i < strlen(httpholder); i++)
//    printf("This is in httpholder: %c\n", httpholder[i]);

// error checking begins here
// checking simply if line starts with GET
if (strncmp(line, "GET", 3) != 0)
{
    error(405);
    return false;
}

// cheking for any " in line
for (int i = 0; i < strlen(line); i++)
{
    if (line[i] == '"')
    {
        error(400);
        return false;
    }
}

// checking if request-target really begiins with a /
if (abpathholder[0] != '/')
{
    error(501);
    return false;
}

// checking if HTTP version is correct
if (strcasecmp(httpholder, "HTTP/1.1") != 0)
{
    error(505);
    return false;
}

abs_path = abpathholder;
query = queryholder;

for (int i = 0; i < strlen(abs_path); i++)
    printf("This is in abs_path: %c\n", abs_path[i]);

for (int i = 0; i < strlen(query); i++)
    printf("This is in query: %c\n", query[i]);

printf("Reached true!\n");

return true;
}
  1. So at first I'm just trying to see if line begins with GET or not. That's pretty straightforward.

  2. Next I'm trying to get where the path starts, and where it ends.

  3. I then calculate from the two, how long the path is

  4. Then I am copying the appropriate number of characters into a new string, that will be later pointed at by abs_path - my idea is that the number of chars in the path will vary every time the client requests a new page

  5. Next, I do almost the same with the HTTP version, but having an easier time, because I can just read up tp \r - this is only for later error checking (if HTTP version is correct)

  6. I then check abstartpath (a string from the start of the absolute path to the end of line) if yes: I set a flag variable to true, if not, then not

  7. If flag variable is true, I attempt to get the length of the query, and store it in a string, and immidiately point the query to it - if not true, I just declare an array of size 1 with \0 in it as per the specs

    1. After that is just a bunch of error checking (all passed, tested with printfs and such)

I'm not sure what goes wrong where. I have a feeling that maybe I shouldn't be sizing the arrays according to the size of abs_path and query, instead maybe just declare an array of LimitRequestLine + 1 and use that, but I'm not sure why my method is not working. Or maybe my whole logic is wrong. Dunno.

Any ideas?

EDIT:

So I have re-written my code to be a bit more clear, but I'm stil getting that darn 301 error (Moved permanently), with too many redirets in chrome, and not properly redirected in firefox.

So here the new walkthrough of my code:

  1. Declaring char arrays to hold my strings and emptying them by memset

  2. Getting vital parts of the string with strchr and strrchr

  3. Declaring two ints to calculate the difference of string lenghts

  4. Checking if there is a query, putting query in my queryholder array and calculating pathend and calculating pathend accordingly

  5. With pathend I can calculate how long the path is, and then I put it in my final array for it (abpathholder)

  6. Gwtting the HTTP variant of the client

  7. Bunch of error checking (all passed)

  8. Setting pointers to my arrays

And that should work, shouldn't it? Or am I misunderstanding the whole point of parse? (Oh don't mind the bunch of printfs on the way, it's just for me to see what's happening)

1

One problem is int pathend = strcspn(abpathstart, lastspace) + 1;. strcspn doesn't work the way you think it does (or wish it did!). From the man page (emphasis added):

The strcspn() function calculates the length of the initial segment of s which consists entirely of bytes not in reject.

strcspn is returning 0, so your pathend is 1.

Why, you may ask? Assuming lastspace is " HTTP/1.1\r\n". The bytes in "reject" are H T P / 1 . \r \n. The first byte in abpathstart is '/'. '/' is one of the bytes to reject. Done. strcspn returns 0.

The php doc on strcspn has a clearer description of how this function operates.

I didn't read much further in your code, because it's downhill from here. I did notice this abpath[0] = abpathstart[0]; Do you want this loop to operate only on index 0?

7
  • Oh, well that fooled me! Thank you for clearing that up, I'll read into the php doc. And no, I meant the variable there instead of 0. I don't know how I didn't catsh that after multiple readthroughs. Thank you, I'll modify my code accordingly, and see what happens! – Bubi Mar 1 '16 at 18:28
  • I decided to reimplement parse as it was getting really messy. Now it's much easier to read and makes much more sense (at least it's supposed to be), with fewer function calls. I'll be hopefully be done with it later on this evening (it's evening here). Mind if I edit my original post and post the current code if it is not working? – Bubi Mar 2 '16 at 16:36
  • Ok, I have posted my new code, I'm still getting error 301 with it, and chrome says too many redirects. I'm sad. – Bubi Mar 3 '16 at 8:22
  • It's a pointer thing, I know what the problem is, I wish I could explain it better. This statement abs_path = abpathholder; changes what (local) abs_path points to. You really want to change the contents of what it points to, so it is available to (main) abs_path. A string function like sprintf or strcpy would be appropriate. (Ditto query). You could add a printf after the call to parse to fact-check me. – DinoCoderSaurus Mar 3 '16 at 16:06
  • You are right. Now I have printfs all over main too (I'm having a real hard time with gdb in this pset). Thank you for all of your help, I'm on the right path now :) – Bubi Mar 3 '16 at 16:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .