File: HttpdP.nc

package info (click to toggle)
tinyos 2.1.2%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: buster, jessie, jessie-kfreebsd, stretch
  • size: 47,476 kB
  • ctags: 36,607
  • sloc: ansic: 63,646; cpp: 14,974; java: 10,358; python: 5,215; makefile: 1,724; sh: 902; asm: 597; xml: 392; perl: 74; awk: 46
file content (152 lines) | stat: -rw-r--r-- 3,349 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

module HttpdP {
  uses {
    interface Leds;
    interface Boot;
    interface Tcp;
  }
} implementation {

  static char *http_okay = "HTTP/1.0 200 OK\r\n\r\n";
  static int http_okay_len = 19;

  enum {
    S_IDLE,
    S_CONNECTED,
    S_REQUEST_PRE,
    S_REQUEST,
    S_HEADER,
    S_BODY,
  };

  enum {
    HTTP_GET,
    HTTP_POST,
  };

  void process_request(int verb, char *request, int len) {
    char reply[24];
    memcpy(reply, "led0: 0 led1: 0 led2: 0\n", 24);

    printfUART("request: '%s'\n", request);

    if (len >= 10 &&
        request[0] == '/' &&
        request[1] == 'r' &&
        request[2] == 'e' &&
        request[3] == 'a' &&
        request[4] == 'd' &&
        request[5] == '/') {
      if (request[6] == 'l' &&
          request[7] == 'e' &&
          request[8] == 'd' &&
          request[9] == 's') {
        uint8_t bitmap = call Leds.get();
        call Tcp.send(http_okay, http_okay_len);
        if (bitmap & 1) reply[6] = '1';
        if (bitmap & 2) reply[14] = '1';
        if (bitmap & 4) reply[22] = '1';
        call Tcp.send(reply, 24);
      }
    }
    call Tcp.close();
  }

  int http_state;
  int req_verb;
  char request_buf[150], *request;
  char tcp_buf[100];

  event void Boot.booted() {
    http_state = S_IDLE;
    call Tcp.bind(80);
  }

  event bool Tcp.accept(struct sockaddr_in6 *from, 
                            void **tx_buf, int *tx_buf_len) {
    if (http_state == S_IDLE) {
      http_state = S_CONNECTED;
      *tx_buf = tcp_buf;
      *tx_buf_len = 100;
      return TRUE;
    }
    printfUART("rejecting connection\n");
    return FALSE;
  }
  event void Tcp.connectDone(error_t e) {
    
  }
  event void Tcp.recv(void *payload, uint16_t len) {
    static int crlf_pos;
    char *msg = payload;
    switch (http_state) {
    case S_CONNECTED:
      crlf_pos = 0;
      request = request_buf;
      if (len < 3) {
        call Tcp.close();
        return;
      }
      if (msg[0] == 'G') {
        req_verb = HTTP_GET;
        msg += 3;
        len -= 3;
      }
      http_state = S_REQUEST_PRE;
    case S_REQUEST_PRE:
      while (len > 0 && *msg == ' ') {
        len--; msg++;
      }
      if (len == 0) break;
      http_state = S_REQUEST;
    case S_REQUEST:
      while (len > 0 && *msg != ' ') {
        *request++ = *msg++;
        len--;
      }
      if (len == 0) break;
      *request++ = '\0';
      http_state = S_HEADER;
    case S_HEADER:
      while (len > 0) {
        switch (crlf_pos) {
        case 0:
        case 2:
          if (*msg == '\r') crlf_pos ++;
          else if (*msg == '\n') crlf_pos += 2;
          else crlf_pos = 0;
          break;
        case 1:
        case 3:
          if (*msg == '\n') crlf_pos ++;
          else crlf_pos = 0;
          break;
        }
        len--; msg++;
        // if crlf == 2, we just finished a header line.  you know.  fyi.
        if (crlf_pos == 4) {
          http_state = S_BODY;
          process_request(req_verb, request_buf, request - request_buf - 1);
          break;
        } 
      }
    if (crlf_pos < 4) break;

    case S_BODY:
      // len might be zero here... just a note.
    default:
      call Tcp.close();
    }
  }

  event void Tcp.closed(error_t e) {
    call Leds.led2Toggle();

    call Tcp.bind(80);
    http_state = S_IDLE;
  }

  event void Tcp.acked() {

  }
}