~rdoering/ubuntu/karmic/erlang/fix-535090

« back to all changes in this revision

Viewing changes to erts/emulator/drivers/common/inet_drv.c

  • Committer: Bazaar Package Importer
  • Author(s): Sergei Golovan
  • Date: 2009-02-15 16:42:52 UTC
  • mfrom: (3.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090215164252-q5x4rcf8a5pbesb1
Tags: 1:12.b.5-dfsg-2
Upload to unstable after lenny is released.

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
#include <sys/types.h>
40
40
#include <errno.h>
41
41
 
 
42
#define IDENTITY(c) c
 
43
#define STRINGIFY_1(b) IDENTITY(#b)
 
44
#define STRINGIFY(a) STRINGIFY_1(a)
 
45
 
42
46
#ifndef _OSE_
43
47
#ifdef HAVE_UNISTD_H
44
48
#include <unistd.h>
48
52
#endif
49
53
#endif
50
54
 
51
 
/* use http processing */
52
 
#define USE_HTTP 
53
55
/* All platforms fail on malloc errors. */
54
56
#define FATAL_MALLOC
55
57
 
292
294
#     define sctp_adaptation_layer_event sctp_adaption_layer_event
293
295
#endif
294
296
 
 
297
static void *h_libsctp = NULL;
 
298
#ifdef __GNUC__
 
299
static typeof(sctp_bindx) *p_sctp_bindx = NULL;
 
300
#else
 
301
static int (*p_sctp_bindx)(int sd, struct sockaddr *addrs,
 
302
                           int addrcnt, int flags) = NULL;
 
303
#endif
 
304
 
295
305
#endif /* SCTP supported */
296
306
 
297
307
#ifndef WANT_NONBLOCKING
412
422
 
413
423
#endif /* __WIN32__ */
414
424
 
 
425
#include "packet_parser.h"
 
426
 
415
427
#define get_int24(s) ((((unsigned char*) (s))[0] << 16) | \
416
428
                      (((unsigned char*) (s))[1] << 8)  | \
417
429
                      (((unsigned char*) (s))[2]))
575
587
#define INET_IFOPT_FLAGS      6
576
588
#define INET_IFOPT_HWADDR     7
577
589
 
578
 
/* INET_LOPT_PACKET options */
579
 
#define TCP_PB_RAW     0
580
 
#define TCP_PB_1       1
581
 
#define TCP_PB_2       2
582
 
#define TCP_PB_4       3
583
 
#define TCP_PB_ASN1    4
584
 
#define TCP_PB_RM      5
585
 
#define TCP_PB_CDR     6
586
 
#define TCP_PB_FCGI    7
587
 
#define TCP_PB_LINE_LF 8
588
 
#define TCP_PB_TPKT    9
589
 
#define TCP_PB_HTTP    10
590
 
#define TCP_PB_HTTPH   11
591
 
 
592
590
/* INET_LOPT_BIT8 options */
593
591
#define INET_BIT8_CLEAR 0
594
592
#define INET_BIT8_SET   1
801
799
    int   sprotocol;            /* socket protocol:
802
800
                                   IPPROTO_TCP|IPPROTO_UDP|IPPROTO_SCTP     */
803
801
    int   sfamily;              /* address family */
804
 
    int   htype;                /* header type (TCP only?) */
 
802
    enum PacketParseType htype; /* header type (TCP only?) */
805
803
    unsigned int psize;         /* max packet size (TCP only?) */
806
804
    int   bit8;                 /* set if bit8f==true and data some data
807
805
                                   seen had the 7th bit set */
850
848
static void tcp_inet_stop(ErlDrvData);
851
849
static void tcp_inet_command(ErlDrvData, char*, int);
852
850
static void tcp_inet_commandv(ErlDrvData, ErlIOVec*);
 
851
static void tcp_inet_flush(ErlDrvData drv_data);
853
852
static void tcp_inet_drv_input(ErlDrvData, ErlDrvEvent);
854
853
static void tcp_inet_drv_output(ErlDrvData data, ErlDrvEvent event);
855
854
static ErlDrvData tcp_inet_start(ErlDrvPort, char* command);
881
880
    tcp_inet_timeout,
882
881
    tcp_inet_commandv,
883
882
    NULL,
884
 
    NULL,
 
883
    tcp_inet_flush,
885
884
    NULL,
886
885
    NULL,
887
886
    ERL_DRV_EXTENDED_MARKER,
990
989
    char*         i_ptr_start;  /* packet start pos in buf */
991
990
    int           i_remain;     /* remaining chars to read */
992
991
    int           tcp_add_flags;/* Additional TCP descriptor flags */
993
 
#ifdef USE_HTTP
994
992
    int           http_state;   /* 0 = response|request  1=headers fields */
995
 
#endif
996
993
    inet_async_multi_op *multi_first;/* NULL == no multi-accept-queue, op is in ordinary queue */
997
994
    inet_async_multi_op *multi_last;
998
995
    MultiTimerData *mtd;        /* Timer structures for multiple accept */
1035
1032
static ErlDrvTermData am_tcp_error;
1036
1033
static ErlDrvTermData am_udp_error;
1037
1034
static ErlDrvTermData am_empty_out_q;
 
1035
static ErlDrvTermData am_ssl_tls;
1038
1036
#ifdef HAVE_SCTP
1039
1037
static ErlDrvTermData am_sctp;
1040
1038
static ErlDrvTermData am_sctp_error;
1887
1885
/* 
1888
1886
** Deliver port data from buffer 
1889
1887
*/
1890
 
static int inet_port_data(inet_descriptor* desc, char* buf, int len)
 
1888
static int inet_port_data(inet_descriptor* desc, const char* buf, int len)
1891
1889
{
1892
1890
    unsigned int hsz = desc->hsz;
1893
1891
 
1894
1892
    DEBUGF(("inet_port_data(%ld): len = %d\r\n", (long)desc->port, len));
1895
1893
 
1896
1894
    if ((desc->mode == INET_MODE_LIST) || (hsz > len))
1897
 
        return driver_output2(desc->port, buf, len, NULL, 0);
 
1895
        return driver_output2(desc->port, (char*)buf, len, NULL, 0);
1898
1896
    else if (hsz > 0)
1899
 
        return driver_output2(desc->port, buf, hsz, buf+hsz, len-hsz);
 
1897
        return driver_output2(desc->port, (char*)buf, hsz, (char*)buf+hsz, len-hsz);
1900
1898
    else
1901
 
        return driver_output(desc->port, buf, len);
 
1899
        return driver_output(desc->port, (char*)buf, len);
1902
1900
}
1903
1901
 
1904
1902
/* 
1919
1917
                                    bin, offs+hsz, len-hsz);
1920
1918
}
1921
1919
 
1922
 
#ifdef USE_HTTP
1923
 
 
1924
 
#define HTTP_HDR_HASH_SIZE  53
1925
 
#define HTTP_METH_HASH_SIZE 13
1926
 
 
1927
 
static char tspecial[128];
1928
 
 
1929
 
static char* http_hdr_strings[] = {
1930
 
  "Cache-Control",
1931
 
  "Connection",
1932
 
  "Date",
1933
 
  "Pragma",
1934
 
  "Transfer-Encoding",
1935
 
  "Upgrade",
1936
 
  "Via",
1937
 
  "Accept",
1938
 
  "Accept-Charset",
1939
 
  "Accept-Encoding",
1940
 
  "Accept-Language",
1941
 
  "Authorization",
1942
 
  "From",
1943
 
  "Host",
1944
 
  "If-Modified-Since",
1945
 
  "If-Match",
1946
 
  "If-None-Match",
1947
 
  "If-Range",
1948
 
  "If-Unmodified-Since",
1949
 
  "Max-Forwards",
1950
 
  "Proxy-Authorization",
1951
 
  "Range",
1952
 
  "Referer",
1953
 
  "User-Agent",
1954
 
  "Age",
1955
 
  "Location",
1956
 
  "Proxy-Authenticate",
1957
 
  "Public",
1958
 
  "Retry-After",
1959
 
  "Server",
1960
 
  "Vary",
1961
 
  "Warning",
1962
 
  "Www-Authenticate",
1963
 
  "Allow",
1964
 
  "Content-Base",
1965
 
  "Content-Encoding",
1966
 
  "Content-Language",
1967
 
  "Content-Length",
1968
 
  "Content-Location",
1969
 
  "Content-Md5",
1970
 
  "Content-Range",
1971
 
  "Content-Type",
1972
 
  "Etag",
1973
 
  "Expires",
1974
 
  "Last-Modified",
1975
 
  "Accept-Ranges",
1976
 
  "Set-Cookie",
1977
 
  "Set-Cookie2",
1978
 
  "X-Forwarded-For",
1979
 
  "Cookie",
1980
 
  "Keep-Alive",
1981
 
  "Proxy-Connection",
1982
 
    NULL
1983
 
};
1984
 
 
1985
 
 
1986
 
static char* http_meth_strings[] = {
1987
 
  "OPTIONS",
1988
 
  "GET",
1989
 
  "HEAD",
1990
 
  "POST",
1991
 
  "PUT",
1992
 
  "DELETE",
1993
 
  "TRACE",
1994
 
    NULL
1995
 
};
1996
 
 
1997
 
typedef struct http_atom {
1998
 
  struct http_atom* next;   /* next in bucket */
1999
 
  unsigned long h;          /* stored hash value */
2000
 
  char* name;
2001
 
  int   len;
2002
 
  int index;                /* index in table + bit-pos */
2003
 
  ErlDrvTermData atom;      /* erlang atom rep */
2004
 
} http_atom_t;
2005
 
 
2006
 
static http_atom_t http_hdr_table[sizeof(http_hdr_strings)/sizeof(char*)];
2007
 
static http_atom_t http_meth_table[sizeof(http_meth_strings)/sizeof(char*)];
2008
 
 
2009
 
static http_atom_t* http_hdr_hash[HTTP_HDR_HASH_SIZE];
2010
 
static http_atom_t* http_meth_hash[HTTP_METH_HASH_SIZE];
2011
 
 
2012
1920
static ErlDrvTermData am_http_eoh;
2013
1921
static ErlDrvTermData am_http_header;
2014
1922
static ErlDrvTermData am_http_request;
2022
1930
static ErlDrvTermData am_https;
2023
1931
static ErlDrvTermData am_scheme;
2024
1932
 
2025
 
 
2026
 
 
2027
 
#define CRNL(ptr) (((ptr)[0] == '\r') && ((ptr)[1] == '\n'))
2028
 
#define NL(ptr)   ((ptr)[0] == '\n')
2029
 
#define SP(ptr)   (((ptr)[0] == ' ') || ((ptr)[0] == '\t'))
2030
 
#define is_tspecial(x) ((((x) > 32) && ((x) < 128)) ? tspecial[(x)] : 1)
2031
 
 
2032
 
#define hash_update(h,c) do { \
2033
 
    unsigned long __g; \
2034
 
    (h) = ((h) << 4) + (c); \
2035
 
    if ((__g = (h) & 0xf0000000)) { \
2036
 
       (h) ^= (__g >> 24); \
2037
 
       (h) ^= __g; \
2038
 
    } \
2039
 
 } while(0)
2040
 
 
2041
 
static void http_hash(char* name, http_atom_t* entry,
2042
 
                      http_atom_t** hash, int hsize)
2043
 
{
2044
 
  unsigned long h = 0;
2045
 
  unsigned char* ptr = (unsigned char*) name;
2046
 
  int ix;
2047
 
  int len = 0;
2048
 
 
2049
 
  while(*ptr != '\0') {
2050
 
    hash_update(h, *ptr);
2051
 
    ptr++;
2052
 
    len++;
2053
 
  }
2054
 
  ix = h % hsize;
2055
 
 
2056
 
  entry->next = hash[ix];
2057
 
  entry->h    = h;
2058
 
  entry->name = name;
2059
 
  entry->len  = len;
2060
 
  entry->atom = driver_mk_atom(name);
2061
 
    
2062
 
  hash[ix] = entry;
2063
 
}
2064
 
 
2065
 
static http_atom_t* http_hash_lookup(char* name, int len,
2066
 
                                     unsigned long h,
2067
 
                                     http_atom_t** hash, int hsize)
2068
 
{
2069
 
  int ix = h % hsize;
2070
 
  http_atom_t* ap = hash[ix];
2071
 
 
2072
 
  while (ap != NULL) {
2073
 
    if ((ap->h == h) && (ap->len == len) && 
2074
 
        (strncmp(ap->name, name, len) == 0))
2075
 
      return ap;
2076
 
    ap = ap->next;
2077
 
  }
2078
 
  return NULL;
2079
 
}
2080
 
     
2081
 
 
2082
 
 
2083
 
static int http_init(void)
2084
 
{
2085
 
  int i;
2086
 
  unsigned char* ptr;
2087
 
 
2088
 
  for (i = 0; i < 33; i++)
2089
 
    tspecial[i] = 1;
2090
 
  for (i = 33; i < 127; i++)
2091
 
    tspecial[i] = 0;
2092
 
  for (ptr = (unsigned char*)"()<>@,;:\\\"/[]?={} \t"; *ptr != '\0'; ptr++)
2093
 
    tspecial[*ptr] = 1;
2094
 
 
2095
 
  INIT_ATOM(http_eoh);
2096
 
  INIT_ATOM(http_header);
2097
 
  INIT_ATOM(http_request);
2098
 
  INIT_ATOM(http_response);
2099
 
  INIT_ATOM(http_error);
2100
 
  INIT_ATOM(abs_path);
2101
 
  INIT_ATOM(absoluteURI);
2102
 
  am_star = driver_mk_atom("*");
2103
 
  INIT_ATOM(undefined);
2104
 
  INIT_ATOM(http);
2105
 
  INIT_ATOM(https);
2106
 
  INIT_ATOM(scheme);
2107
 
 
2108
 
  for (i = 0; i < HTTP_HDR_HASH_SIZE; i++)
2109
 
    http_hdr_hash[i] = NULL;
2110
 
  for (i = 0; http_hdr_strings[i] != NULL; i++) {
2111
 
    http_hdr_table[i].index = i;
2112
 
    http_hash(http_hdr_strings[i], 
2113
 
              &http_hdr_table[i], 
2114
 
              http_hdr_hash, HTTP_HDR_HASH_SIZE);
2115
 
  }
2116
 
 
2117
 
  for (i = 0; i < HTTP_METH_HASH_SIZE; i++)
2118
 
    http_meth_hash[i] = NULL;
2119
 
  for (i = 0; http_meth_strings[i] != NULL; i++) {
2120
 
    http_meth_table[i].index = i;
2121
 
    http_hash(http_meth_strings[i],
2122
 
              &http_meth_table[i], 
2123
 
              http_meth_hash, HTTP_METH_HASH_SIZE);
2124
 
  }
2125
 
  return 0;
2126
 
}
2127
 
 
2128
 
static int
2129
 
http_response_message(tcp_descriptor* desc, int major, int minor, int status,
2130
 
                      char* phrase, int phrase_len)
2131
 
{
2132
 
  int i = 0;
2133
 
  ErlDrvTermData spec[27];
2134
 
 
2135
 
  if (desc->inet.active == INET_PASSIVE) {
2136
 
    /* {inet_async,S,Ref,{ok,{http_response,Version,Status,Phrase}}} */
2137
 
    int req;
2138
 
    int aid;
 
1933
static int http_response_inetdrv(void *arg, int major, int minor,
 
1934
                                 int status, const char* phrase, int phrase_len)
 
1935
{
 
1936
    tcp_descriptor* desc = (tcp_descriptor*) arg;
 
1937
    int i = 0;
 
1938
    ErlDrvTermData spec[27];
2139
1939
    ErlDrvTermData caller;
2140
 
 
2141
 
    if (deq_async(INETP(desc), &aid, &caller, &req) < 0)
2142
 
      return -1;
2143
 
    i = LOAD_ATOM(spec, i,  am_inet_async);
2144
 
    i = LOAD_PORT(spec, i,  desc->inet.dport);
2145
 
    i = LOAD_INT(spec, i,   aid);
2146
 
    i = LOAD_ATOM(spec, i,  am_ok);
2147
 
    i = LOAD_ATOM(spec, i,  am_http_response);
2148
 
    i = LOAD_INT(spec, i, major);
2149
 
    i = LOAD_INT(spec, i, minor);
2150
 
    i = LOAD_TUPLE(spec, i, 2);
2151
 
    i = LOAD_INT(spec, i, status);
2152
 
    i = LOAD_STRING(spec, i, phrase, phrase_len);
2153
 
    i = LOAD_TUPLE(spec, i, 4);
2154
 
    i = LOAD_TUPLE(spec, i, 2);
2155
 
    i = LOAD_TUPLE(spec, i, 4);
2156
 
    return driver_send_term(desc->inet.port, caller, spec, i);
2157
 
  }
2158
 
  else {
2159
 
    /* {http_response, S, Version, Status, Phrase} */
2160
 
    i = LOAD_ATOM(spec, i,  am_http_response);
2161
 
    i = LOAD_PORT(spec, i,  desc->inet.dport);
2162
 
    i = LOAD_INT(spec, i, major);
2163
 
    i = LOAD_INT(spec, i, minor);
2164
 
    i = LOAD_TUPLE(spec, i, 2);
2165
 
    i = LOAD_INT(spec, i, status);
2166
 
    i = LOAD_STRING(spec, i, phrase, phrase_len);
2167
 
    i = LOAD_TUPLE(spec, i, 5);
2168
 
    return driver_output_term(desc->inet.port, spec, i);
2169
 
  }
2170
 
}
2171
 
 
2172
 
/*
2173
 
** Handle URI syntax:
2174
 
**
2175
 
**  Request-URI    = "*" | absoluteURI | abs_path
2176
 
**  absoluteURI    = scheme ":" *( uchar | reserved )
2177
 
**  net_path       = "//" net_loc [ abs_path ]
2178
 
**  abs_path       = "/" rel_path
2179
 
**  rel_path       = [ path ] [ ";" params ] [ "?" query ]
2180
 
**  path           = fsegment *( "/" segment )
2181
 
**  fsegment       = 1*pchar
2182
 
**  segment        = *pchar
2183
 
**  params         = param *( ";" param )
2184
 
**  param          = *( pchar | "/" )
2185
 
**  query          = *( uchar | reserved )
2186
 
**
2187
 
**  http_URL       = "http:" "//" host [ ":" port ] [ abs_path ]
2188
 
**
2189
 
**  host           = <A legal Internet host domain name
2190
 
**                   or IP address (in dotted-decimal form),
2191
 
**                   as defined by Section 2.1 of RFC 1123>
2192
 
**  port           = *DIGIT
2193
 
**
2194
 
**  {absoluteURI, <scheme>, <host>, <port>, <path+params+query>}
2195
 
**       when <scheme> = http | https
2196
 
**  {scheme, <scheme>, <chars>}
2197
 
**       wheb <scheme> is something else then http or https
2198
 
**  {abs_path,  <path>}
2199
 
**
2200
 
**  <string>  (unknown form)
2201
 
**
2202
 
*/
2203
 
 
2204
 
/* host [ ":" port ] [ abs_path ] */
2205
 
static int
2206
 
http_load_absoluteURI(ErlDrvTermData* spec, int i, ErlDrvTermData scheme,
2207
 
                      char* uri_ptr, int uri_len)
2208
 
{
2209
 
  char* p;
2210
 
  char* abs_path_ptr;
2211
 
  int   abs_path_len;
2212
 
 
2213
 
  if ((p = memchr(uri_ptr, '/', uri_len)) == NULL) {
2214
 
    /* host [":" port] */
2215
 
    abs_path_ptr = "/";
2216
 
    abs_path_len = 1;
2217
 
  }
2218
 
  else {
2219
 
    int n = (p - uri_ptr);
2220
 
 
2221
 
    abs_path_ptr = p;
2222
 
    abs_path_len = uri_len - n;
2223
 
    uri_len = n;
2224
 
  }
2225
 
  i = LOAD_ATOM(spec, i, am_absoluteURI);
2226
 
  i = LOAD_ATOM(spec, i, scheme);
2227
 
 
2228
 
  /* host[:port]  */
2229
 
  if ((p = memchr(uri_ptr, ':', uri_len)) == NULL) {
2230
 
    i = LOAD_STRING(spec, i, uri_ptr, uri_len);
2231
 
    i = LOAD_ATOM(spec, i, am_undefined);
2232
 
  }
2233
 
  else {
2234
 
    int n = (p - uri_ptr);
2235
 
    int port = 0;
2236
 
 
2237
 
    i = LOAD_STRING(spec, i, uri_ptr, n);
2238
 
    n = uri_len - (n+1);
2239
 
    p++;
2240
 
    while(n && isdigit((int) *p)) {
2241
 
      port = port*10 + (*p - '0');
2242
 
      n--;
2243
 
      p++;
2244
 
    }
2245
 
    if ((n != 0) || (port == 0))
2246
 
      i = LOAD_ATOM(spec, i, am_undefined);
2247
 
    else
2248
 
      i = LOAD_INT(spec, i, port);
2249
 
  }
2250
 
  i = LOAD_STRING(spec, i, abs_path_ptr, abs_path_len);
2251
 
  i = LOAD_TUPLE(spec, i, 5);
2252
 
  return i;
2253
 
}
2254
 
 
2255
 
static int http_load_uri(ErlDrvTermData* spec, int i, char* uri_ptr, int uri_len)
2256
 
{
2257
 
  if ((uri_len == 1) && (uri_ptr[0] == '*'))
2258
 
    i = LOAD_ATOM(spec, i, am_star);
2259
 
  else if ((uri_len <= 1) || (uri_ptr[0] == '/')) {
2260
 
    i = LOAD_ATOM(spec, i, am_abs_path);
2261
 
    i = LOAD_STRING(spec, i, uri_ptr, uri_len);
2262
 
    i = LOAD_TUPLE(spec, i, 2);
2263
 
  }
2264
 
  else {
2265
 
    if ((uri_len>=7) && (STRNCASECMP(uri_ptr, "http://", 7) == 0)) {
2266
 
      uri_len -= 7;
2267
 
      uri_ptr += 7;
2268
 
      return http_load_absoluteURI(spec, i, am_http, uri_ptr, uri_len);
2269
 
    }
2270
 
    else if ((uri_len>=8) && (STRNCASECMP(uri_ptr, "https://", 8) == 0)) {
2271
 
      uri_len -= 8;
2272
 
      uri_ptr += 8;    
2273
 
      return http_load_absoluteURI(spec, i, am_https, uri_ptr,uri_len);
2274
 
    }
2275
 
    else {
2276
 
      char* ptr;
2277
 
      if ((ptr = memchr(uri_ptr, ':', uri_len)) == NULL)
2278
 
        i = LOAD_STRING(spec, i, uri_ptr, uri_len);
2279
 
      else {
2280
 
        int slen = ptr - uri_ptr;
2281
 
        i = LOAD_ATOM(spec, i, am_scheme);
2282
 
        i = LOAD_STRING(spec, i, uri_ptr, slen);
2283
 
        i = LOAD_STRING(spec, i, uri_ptr+(slen+1), uri_len-(slen+1));
2284
 
        i = LOAD_TUPLE(spec, i, 3);
2285
 
      }
2286
 
    }
2287
 
  }
2288
 
  return i;
2289
 
}
2290
 
 
2291
 
static int
2292
 
http_request_message(tcp_descriptor* desc, http_atom_t* meth, char* meth_ptr,
2293
 
                     int meth_len, char* uri_ptr, int uri_len,
 
1940
    
 
1941
    if (desc->inet.active == INET_PASSIVE) {
 
1942
        /* {inet_async,S,Ref,{ok,{http_response,Version,Status,Phrase}}} */
 
1943
        int req;
 
1944
        int aid;
 
1945
        
 
1946
        if (deq_async(INETP(desc), &aid, &caller, &req) < 0)
 
1947
            return -1;
 
1948
        i = LOAD_ATOM(spec, i,  am_inet_async);
 
1949
        i = LOAD_PORT(spec, i,  desc->inet.dport);
 
1950
        i = LOAD_INT(spec, i,   aid);
 
1951
        i = LOAD_ATOM(spec, i,  am_ok);
 
1952
    }
 
1953
    else {
 
1954
        /* {http, S, {http_response,Version,Status,Phrase}} */
 
1955
        i = LOAD_ATOM(spec, i, am_http);
 
1956
        i = LOAD_PORT(spec, i, desc->inet.dport);
 
1957
    }
 
1958
    i = LOAD_ATOM(spec, i,  am_http_response);
 
1959
    i = LOAD_INT(spec, i, major);
 
1960
    i = LOAD_INT(spec, i, minor);
 
1961
    i = LOAD_TUPLE(spec, i, 2);
 
1962
    i = LOAD_INT(spec, i, status);
 
1963
    i = LOAD_STRING(spec, i, phrase, phrase_len);
 
1964
    i = LOAD_TUPLE(spec, i, 4);
 
1965
    
 
1966
    if (desc->inet.active == INET_PASSIVE) {
 
1967
        i = LOAD_TUPLE(spec, i, 2);
 
1968
        i = LOAD_TUPLE(spec, i, 4);
 
1969
        ASSERT(i<=27);
 
1970
        return driver_send_term(desc->inet.port, caller, spec, i);
 
1971
    }
 
1972
    else {
 
1973
        i = LOAD_TUPLE(spec, i, 3);
 
1974
        ASSERT(i<=27);
 
1975
        return driver_output_term(desc->inet.port, spec, i);
 
1976
    }
 
1977
}
 
1978
 
 
1979
static int http_load_uri(ErlDrvTermData* spec, int i, const PacketHttpURI* uri)
 
1980
{
 
1981
    ErlDrvTermData scheme;
 
1982
 
 
1983
    switch (uri->type) {
 
1984
    case URI_STAR:
 
1985
        i = LOAD_ATOM(spec, i, am_star);
 
1986
        break;
 
1987
    case URI_ABS_PATH:
 
1988
        i = LOAD_ATOM(spec, i, am_abs_path);
 
1989
        i = LOAD_STRING(spec, i, uri->s1_ptr, uri->s1_len);
 
1990
        i = LOAD_TUPLE(spec, i, 2);
 
1991
        break;
 
1992
    case URI_HTTP:
 
1993
        scheme = am_http;
 
1994
        goto http_common;
 
1995
    case URI_HTTPS:
 
1996
        scheme = am_https;
 
1997
    http_common:
 
1998
        i = LOAD_ATOM(spec, i, am_absoluteURI);
 
1999
        i = LOAD_ATOM(spec, i, scheme);
 
2000
        i = LOAD_STRING(spec, i, uri->s1_ptr, uri->s1_len);
 
2001
        if (uri->port == 0) {
 
2002
            i = LOAD_ATOM(spec, i, am_undefined);
 
2003
        } else {
 
2004
            i = LOAD_INT(spec, i, uri->port);
 
2005
        }
 
2006
        i = LOAD_STRING(spec, i, uri->s2_ptr, uri->s1_len);
 
2007
        i = LOAD_TUPLE(spec, i, 5);
 
2008
        break;
 
2009
 
 
2010
    case URI_STRING:
 
2011
        i = LOAD_STRING(spec, i, uri->s1_ptr, uri->s1_len);
 
2012
        break;
 
2013
    case URI_SCHEME:
 
2014
        i = LOAD_ATOM(spec, i, am_scheme);
 
2015
        i = LOAD_STRING(spec, i, uri->s1_ptr, uri->s1_len);
 
2016
        i = LOAD_STRING(spec, i, uri->s2_ptr, uri->s2_len);
 
2017
        i = LOAD_TUPLE(spec, i, 3);
 
2018
    }
 
2019
    return i;
 
2020
}
 
2021
 
 
2022
 
 
2023
static int
 
2024
http_request_inetdrv(void* arg, const http_atom_t* meth, const char* meth_ptr,
 
2025
                     int meth_len, const PacketHttpURI* uri,
2294
2026
                     int major, int minor)
2295
2027
{
2296
 
  int i = 0;
2297
 
  ErlDrvTermData spec[43];
2298
 
 
2299
 
  if (desc->inet.active == INET_PASSIVE) {
2300
 
    /* {inet_async, S, Ref, {ok,{http_request,Meth,Uri,Version}}} */
2301
 
    int req;
2302
 
    int aid;
 
2028
    tcp_descriptor* desc = (tcp_descriptor*) arg;
 
2029
    int i = 0;
 
2030
    ErlDrvTermData spec[43];
2303
2031
    ErlDrvTermData caller;
2304
 
 
2305
 
    if (deq_async(INETP(desc), &aid, &caller, &req) < 0)
2306
 
      return -1;
2307
 
    i = LOAD_ATOM(spec, i,  am_inet_async);
2308
 
    i = LOAD_PORT(spec, i,  desc->inet.dport);
2309
 
    i = LOAD_INT(spec, i,   aid);
2310
 
    i = LOAD_ATOM(spec, i,  am_ok);
2311
 
    i = LOAD_ATOM(spec, i,  am_http_request);
2312
 
    if (meth != NULL)
2313
 
      i = LOAD_ATOM(spec, i, meth->atom);
2314
 
    else
2315
 
      i = LOAD_STRING(spec, i, meth_ptr, meth_len);
2316
 
    i = http_load_uri(spec, i, uri_ptr, uri_len);
2317
 
    i = LOAD_INT(spec, i, major);
2318
 
    i = LOAD_INT(spec, i, minor);
2319
 
    i = LOAD_TUPLE(spec, i, 2);
2320
 
    i = LOAD_TUPLE(spec, i, 4);
2321
 
    i = LOAD_TUPLE(spec, i, 2);
2322
 
    i = LOAD_TUPLE(spec, i, 4);
2323
 
    ASSERT(i <= 43);
2324
 
    return driver_send_term(desc->inet.port, caller, spec, i);
2325
 
  }
2326
 
  else {
2327
 
    /* {http_request, S, Meth, Uri, Version} */
2328
 
    i = LOAD_ATOM(spec, i,  am_http_request);
2329
 
    i = LOAD_PORT(spec, i,  desc->inet.dport);
2330
 
    if (meth != NULL)
2331
 
      i = LOAD_ATOM(spec, i, meth->atom);
2332
 
    else
2333
 
      i = LOAD_STRING(spec, i, meth_ptr, meth_len);
2334
 
    i = http_load_uri(spec, i, uri_ptr, uri_len);
2335
 
    i = LOAD_INT(spec, i, major);
2336
 
    i = LOAD_INT(spec, i, minor);
2337
 
    i = LOAD_TUPLE(spec, i, 2);
2338
 
    i = LOAD_TUPLE(spec, i, 5);
2339
 
    ASSERT(i <= 43);
2340
 
    return driver_output_term(desc->inet.port, spec, i);
2341
 
  }
 
2032
    
 
2033
    if (desc->inet.active == INET_PASSIVE) {
 
2034
        /* {inet_async, S, Ref, {ok,{http_request,Meth,Uri,Version}}} */
 
2035
        int req;
 
2036
        int aid;
 
2037
        
 
2038
        if (deq_async(INETP(desc), &aid, &caller, &req) < 0)
 
2039
            return -1;
 
2040
        i = LOAD_ATOM(spec, i,  am_inet_async);
 
2041
        i = LOAD_PORT(spec, i,  desc->inet.dport);
 
2042
        i = LOAD_INT(spec, i,   aid);
 
2043
        i = LOAD_ATOM(spec, i,  am_ok);
 
2044
    }
 
2045
    else {
 
2046
        /* {http, S, {http_request,Meth,Uri,Version}}} */
 
2047
        i = LOAD_ATOM(spec, i, am_http);
 
2048
        i = LOAD_PORT(spec, i, desc->inet.dport);
 
2049
    }
 
2050
 
 
2051
    i = LOAD_ATOM(spec, i,  am_http_request);
 
2052
    if (meth != NULL)
 
2053
      i = LOAD_ATOM(spec, i, meth->atom);
 
2054
    else
 
2055
      i = LOAD_STRING(spec, i, meth_ptr, meth_len);
 
2056
    i = http_load_uri(spec, i, uri);
 
2057
    i = LOAD_INT(spec, i, major);
 
2058
    i = LOAD_INT(spec, i, minor);
 
2059
    i = LOAD_TUPLE(spec, i, 2);
 
2060
    i = LOAD_TUPLE(spec, i, 4);
 
2061
 
 
2062
    if (desc->inet.active == INET_PASSIVE) {
 
2063
        i = LOAD_TUPLE(spec, i, 2);
 
2064
        i = LOAD_TUPLE(spec, i, 4);
 
2065
        ASSERT(i <= 43);
 
2066
        return driver_send_term(desc->inet.port, caller, spec, i);
 
2067
    }
 
2068
    else {
 
2069
        i = LOAD_TUPLE(spec, i, 3);
 
2070
        ASSERT(i <= 43);
 
2071
        return driver_output_term(desc->inet.port, spec, i);
 
2072
    }
2342
2073
}
2343
2074
 
2344
2075
static int
2345
 
http_header_message(tcp_descriptor* desc, http_atom_t* name, char* name_ptr,
2346
 
                    int name_len, char* value_ptr, int value_len)
 
2076
http_header_inetdrv(void* arg, const http_atom_t* name, const char* name_ptr,
 
2077
                    int name_len, const char* value_ptr, int value_len)
2347
2078
{
2348
 
  int i = 0;
2349
 
  ErlDrvTermData spec[26];
2350
 
 
2351
 
  if (desc->inet.active == INET_PASSIVE) {
2352
 
    /* {inet_async,S,Ref,{ok,{http_header,Bit,Name,IValue,Value}} */
2353
 
    int req;
2354
 
    int aid;
 
2079
    tcp_descriptor* desc = (tcp_descriptor*) arg;
 
2080
    int i = 0;
 
2081
    ErlDrvTermData spec[26];
2355
2082
    ErlDrvTermData caller;
 
2083
    
 
2084
    if (desc->inet.active == INET_PASSIVE) {
 
2085
        /* {inet_async,S,Ref,{ok,{http_header,Bit,Name,IValue,Value}} */
 
2086
        int req;
 
2087
        int aid;
 
2088
        
 
2089
        
 
2090
        if (deq_async(INETP(desc), &aid, &caller, &req) < 0)
 
2091
            return -1;
 
2092
        i = LOAD_ATOM(spec, i,  am_inet_async);
 
2093
        i = LOAD_PORT(spec, i,  desc->inet.dport);
 
2094
        i = LOAD_INT(spec, i,   aid);
 
2095
        i = LOAD_ATOM(spec, i,  am_ok);
 
2096
    }
 
2097
    else {
 
2098
        /* {http, S, {http_header,Bit,Name,IValue,Value}} */
 
2099
        i = LOAD_ATOM(spec, i, am_http);
 
2100
        i = LOAD_PORT(spec, i, desc->inet.dport);
 
2101
    }
2356
2102
 
2357
 
    if (deq_async(INETP(desc), &aid, &caller, &req) < 0)
2358
 
      return -1;
2359
 
    i = LOAD_ATOM(spec, i,  am_inet_async);
2360
 
    i = LOAD_PORT(spec, i,  desc->inet.dport);
2361
 
    i = LOAD_INT(spec, i,   aid);
2362
 
    i = LOAD_ATOM(spec, i,  am_ok);
2363
2103
    i = LOAD_ATOM(spec, i,  am_http_header);
2364
2104
    if (name != NULL) {
2365
2105
      i = LOAD_INT(spec, i,  name->index+1);
2372
2112
    i = LOAD_ATOM(spec, i, am_undefined);
2373
2113
    i = LOAD_STRING(spec, i, value_ptr, value_len);
2374
2114
    i = LOAD_TUPLE(spec, i, 5);
2375
 
    i = LOAD_TUPLE(spec, i, 2);
2376
 
    i = LOAD_TUPLE(spec, i, 4);
2377
 
    ASSERT(i <= 26);
2378
 
    return driver_send_term(desc->inet.port, caller, spec, i);
2379
 
  }
2380
 
  else {
2381
 
    /* {http_header,S,Bit,Name,Code,Value} */
2382
 
    i = LOAD_ATOM(spec, i,  am_http_header);
2383
 
    i = LOAD_PORT(spec, i,  desc->inet.dport);
2384
 
    if (name != NULL) {
2385
 
      i = LOAD_INT(spec, i,  name->index+1);
2386
 
      i = LOAD_ATOM(spec, i, name->atom);
 
2115
 
 
2116
    if (desc->inet.active == INET_PASSIVE) {
 
2117
        i = LOAD_TUPLE(spec, i, 2);
 
2118
        i = LOAD_TUPLE(spec, i, 4);
 
2119
        ASSERT(i <= 26);
 
2120
        return driver_send_term(desc->inet.port, caller, spec, i);
2387
2121
    }
2388
2122
    else {
2389
 
      i = LOAD_INT(spec, i,  0);
2390
 
      i = LOAD_STRING(spec, i, name_ptr, name_len);
 
2123
        i = LOAD_TUPLE(spec, i, 3);
 
2124
        ASSERT(i <= 26);
 
2125
        return driver_output_term(desc->inet.port, spec, i);
2391
2126
    }
2392
 
    i = LOAD_ATOM(spec, i, am_undefined);
2393
 
    i = LOAD_STRING(spec, i, value_ptr, value_len);
2394
 
    i = LOAD_TUPLE(spec, i, 6);
2395
 
    ASSERT(i <= 26);
2396
 
    return driver_output_term(desc->inet.port, spec, i);
2397
 
  }
2398
2127
}
2399
2128
 
2400
 
static int http_eoh_message(tcp_descriptor* desc)
 
2129
static int http_eoh_inetdrv(void* arg)
2401
2130
{
 
2131
  tcp_descriptor* desc = (tcp_descriptor*) arg;
2402
2132
  int i = 0;
2403
2133
  ErlDrvTermData spec[14];
2404
2134
 
2421
2151
    return driver_send_term(desc->inet.port, caller, spec, i);
2422
2152
  }
2423
2153
  else {
2424
 
    /* {http_eoh,S} */
2425
 
    i = LOAD_ATOM(spec, i,  am_http_eoh);
2426
 
    i = LOAD_PORT(spec, i,  desc->inet.dport);
2427
 
    i = LOAD_TUPLE(spec, i, 2);
2428
 
    ASSERT(i <= 14);
2429
 
    return driver_output_term(desc->inet.port, spec, i);
 
2154
      /* {http, S, http_eoh} */
 
2155
      i = LOAD_ATOM(spec, i,  am_http);
 
2156
      i = LOAD_PORT(spec, i,  desc->inet.dport);
 
2157
      i = LOAD_ATOM(spec, i,  am_http_eoh);
 
2158
      i = LOAD_TUPLE(spec, i, 3);
 
2159
      ASSERT(i <= 14);
 
2160
      return driver_output_term(desc->inet.port, spec, i);
2430
2161
  }
2431
2162
}
2432
2163
 
2433
 
static int http_error_message(tcp_descriptor* desc, char* buf, int len)
 
2164
static int http_error_inetdrv(void* arg, const char* buf, int len)
2434
2165
{
 
2166
  tcp_descriptor* desc = (tcp_descriptor*) arg;
2435
2167
  int i = 0;
2436
2168
  ErlDrvTermData spec[19];
2437
2169
 
2456
2188
    return driver_send_term(desc->inet.port, caller, spec, i);
2457
2189
  }
2458
2190
  else {
2459
 
    /* {http_error,S,Line} */
2460
 
    i = LOAD_ATOM(spec, i,  am_http_error);
 
2191
      /* {http, S, {http_error,Line} */
 
2192
      i = LOAD_ATOM(spec, i,  am_http);
 
2193
      i = LOAD_PORT(spec, i,  desc->inet.dport);
 
2194
      i = LOAD_ATOM(spec, i,  am_http_error);
 
2195
      i = LOAD_STRING(spec, i, buf, len);
 
2196
      i = LOAD_TUPLE(spec, i, 2);
 
2197
      i = LOAD_TUPLE(spec, i, 3);
 
2198
      ASSERT(i <= 19);
 
2199
      return driver_output_term(desc->inet.port, spec, i);
 
2200
  }
 
2201
}
 
2202
 
 
2203
 
 
2204
static
 
2205
int ssl_tls_inetdrv(void* arg, unsigned type, unsigned major, unsigned minor,
 
2206
                    const char* buf, int len, const char* prefix, int plen)
 
2207
{
 
2208
    tcp_descriptor* desc = (tcp_descriptor*) arg;
 
2209
    int i = 0;
 
2210
    ErlDrvTermData spec[28];
 
2211
    ErlDrvTermData caller;
 
2212
    ErlDrvBinary* bin;
 
2213
    int ret;
 
2214
 
 
2215
    if ((bin = driver_alloc_binary(plen+len)) == NULL)
 
2216
        return async_error(&desc->inet, ENOMEM);
 
2217
    memcpy(bin->orig_bytes+plen, buf, len);
 
2218
    if (plen) {
 
2219
        memcpy(bin->orig_bytes, prefix, plen);
 
2220
        len += plen;
 
2221
    }
 
2222
 
 
2223
    if (desc->inet.active == INET_PASSIVE) {
 
2224
        /* {inet_async,S,Ref,{ok,{ssl_tls,...}}} */
 
2225
        int req;
 
2226
        int aid;
 
2227
 
 
2228
        if (deq_async(INETP(desc), &aid, &caller, &req) < 0) {
 
2229
            ret = -1;
 
2230
            goto done;
 
2231
        }
 
2232
        i = LOAD_ATOM(spec, i,  am_inet_async);
 
2233
        i = LOAD_PORT(spec, i,  desc->inet.dport);
 
2234
        i = LOAD_INT(spec, i,   aid);
 
2235
        i = LOAD_ATOM(spec, i,  am_ok);
 
2236
    }
 
2237
 
 
2238
    /* {ssl_tls,S,ContentType,{Major,Minor},Bin} */
 
2239
    i = LOAD_ATOM(spec, i,  am_ssl_tls);
2461
2240
    i = LOAD_PORT(spec, i,  desc->inet.dport);
2462
 
    i = LOAD_STRING(spec, i, buf, len);
2463
 
    i = LOAD_TUPLE(spec, i, 3);
2464
 
    ASSERT(i <= 19);
2465
 
    return driver_output_term(desc->inet.port, spec, i);
2466
 
  }
 
2241
    i = LOAD_INT(spec, i,   type);
 
2242
    i = LOAD_INT(spec, i,   major);
 
2243
    i = LOAD_INT(spec, i,   minor);
 
2244
    i = LOAD_TUPLE(spec, i, 2);
 
2245
    i = LOAD_BINARY(spec, i, bin, 0, len);
 
2246
    i = LOAD_TUPLE(spec, i, 5);
 
2247
 
 
2248
    if (desc->inet.active == INET_PASSIVE) {
 
2249
        i = LOAD_TUPLE(spec, i, 2);
 
2250
        i = LOAD_TUPLE(spec, i, 4);
 
2251
        ASSERT(i <= 28);
 
2252
        ret = driver_send_term(desc->inet.port, caller, spec, i);
 
2253
    }
 
2254
    else {
 
2255
        ASSERT(i <= 28);
 
2256
        ret = driver_output_term(desc->inet.port, spec, i);
 
2257
    }
 
2258
done:
 
2259
    driver_free_binary(bin);
 
2260
    return ret;
2467
2261
}
2468
2262
 
2469
 
/*
2470
 
** load http message:
2471
 
**  {http_eoh, S}                          - end of headers
2472
 
**  {http_header,   S, Key, Value}         - Key = atom() | string()
2473
 
**  {http_request,  S, Method,Url,Version}
2474
 
**  {http_response, S, Version, Status, Message}
2475
 
**  {http_error,    S, Error-Line}
2476
 
*/
2477
 
static int http_message(tcp_descriptor* desc, char* buf, int len)
 
2263
 
 
2264
static PacketCallbacks packet_callbacks =
2478
2265
{
2479
 
  char* ptr = buf;
2480
 
  int n = len;
2481
 
 
2482
 
  /* remove trailing CRNL (accept NL as well) */
2483
 
  if ((n >= 2) && (buf[n-2] == '\r'))
2484
 
    n -= 2;
2485
 
  else if ((n >= 1) && (buf[n-1] == '\n'))
2486
 
    n -= 1;
2487
 
 
2488
 
  if (desc->http_state == 0) {
2489
 
    unsigned long h;
2490
 
    http_atom_t* meth;
2491
 
    char* meth_ptr;
2492
 
    int   meth_len;
2493
 
    int c;
2494
 
    /* start-line = Request-Line | Status-Line */
2495
 
    if (n == 0)
2496
 
        return -1;
2497
 
    h = 0;
2498
 
    meth_ptr = ptr;
2499
 
    while (n && !is_tspecial((unsigned char)*ptr)) {
2500
 
      c = *ptr;
2501
 
      hash_update(h, c);
2502
 
      ptr++;
2503
 
      n--;
2504
 
    }
2505
 
    if ((meth_len = (ptr - meth_ptr)) == 0)
2506
 
      return -1;
2507
 
    meth = http_hash_lookup(meth_ptr, meth_len, h,
2508
 
                            http_meth_hash, HTTP_METH_HASH_SIZE);
2509
 
    if (n) {
2510
 
      if ((*ptr == '/') && (strncmp(buf, "HTTP", 4) == 0)) {
2511
 
        int major  = 0;
2512
 
        int minor  = 0;
2513
 
        int status = 0;
2514
 
        /* Status-Line = HTTP-Version SP 
2515
 
         *              Status-Code SP Reason-Phrase 
2516
 
         *              CRNL
2517
 
         * HTTP-Version   = "HTTP" "/" 1*DIGIT "." 1*DIGIT
2518
 
         */
2519
 
        ptr++;
2520
 
        n--;
2521
 
        if (!n || !isdigit((int) *ptr)) return -1;
2522
 
        while(n && isdigit((int) *ptr)) {
2523
 
          major = 10*major + (*ptr - '0');
2524
 
          ptr++;
2525
 
          n--;
2526
 
        }
2527
 
        if (!n || (*ptr != '.'))
2528
 
          return -1;
2529
 
        ptr++;
2530
 
        n--;
2531
 
        if (!n || !isdigit((int) *ptr)) return -1;
2532
 
        while(n && isdigit((int) *ptr)) {
2533
 
          minor = 10*minor + (*ptr - '0');
2534
 
          ptr++;
2535
 
          n--;
2536
 
        }
2537
 
        if (!n || !SP(ptr))
2538
 
          return -1;
2539
 
 
2540
 
        while(n && SP(ptr)) { ptr++; n--; }
2541
 
 
2542
 
        while(n && isdigit((int) *ptr)) {
2543
 
          status = 10*status + (*ptr - '0');
2544
 
          ptr++;
2545
 
          n--;
2546
 
        }
2547
 
        if (!n || !SP(ptr))
2548
 
          return -1;
2549
 
 
2550
 
        while(n && SP(ptr)) { ptr++; n--; }
2551
 
 
2552
 
        /* NOTE: the syntax allows empty reason phrases */
2553
 
        desc->http_state++;
2554
 
 
2555
 
        return http_response_message(desc, major, minor, status,
2556
 
                                     (char*)ptr, n);
2557
 
      }
2558
 
      else if (SP(ptr)) {
2559
 
        /* Request-Line = Method SP Request-URI SP HTTP-Version CRLF */
2560
 
        char* uri_ptr;
2561
 
        int   uri_len;
2562
 
        int major  = 0;
2563
 
        int minor  = 0;
2564
 
        
2565
 
        while(n && SP(ptr)) { ptr++; n--; }
2566
 
        uri_ptr = ptr;
2567
 
        while(n && !SP(ptr)) { ptr++; n--; }
2568
 
        if ((uri_len = (ptr - uri_ptr)) == 0)
2569
 
          return -1;
2570
 
        while(n && SP(ptr)) { ptr++; n--; }
2571
 
        if (n == 0) {
2572
 
          desc->http_state++;
2573
 
          return http_request_message(desc, meth,
2574
 
                                      meth_ptr, meth_len,
2575
 
                                      uri_ptr, uri_len,
2576
 
                                      0, 9);
2577
 
        }
2578
 
        if (n < 8)
2579
 
          return -1;
2580
 
        if (strncmp(ptr, "HTTP/", 5) != 0)
2581
 
          return -1;
2582
 
        ptr += 5;
2583
 
        n   -= 5;
2584
 
 
2585
 
        if (!n || !isdigit((int) *ptr)) return -1;
2586
 
        while(n && isdigit((int) *ptr)) {
2587
 
          major = 10*major + (*ptr - '0');
2588
 
          ptr++;
2589
 
          n--;
2590
 
        }
2591
 
 
2592
 
        if (!n || (*ptr != '.'))
2593
 
          return -1;
2594
 
        ptr++;
2595
 
        n--;
2596
 
 
2597
 
        if (!n || !isdigit((int) *ptr)) return -1;
2598
 
        while(n && isdigit((int) *ptr)) {
2599
 
          minor = 10*minor + (*ptr - '0');
2600
 
          ptr++;
2601
 
          n--;
2602
 
        }
2603
 
        desc->http_state++;
2604
 
        return http_request_message(desc, meth,
2605
 
                                    meth_ptr, meth_len,
2606
 
                                    uri_ptr, uri_len,
2607
 
                                    major, minor);
2608
 
      }
2609
 
    }
2610
 
    return -1;
2611
 
  }
2612
 
  else {
2613
 
    int up = 1;      /* make next char uppercase */
2614
 
    http_atom_t* name;
2615
 
    char* name_ptr;
2616
 
    int   name_len;
2617
 
    unsigned long h;
2618
 
 
2619
 
    if (n == 0) {
2620
 
      /* end of headers */
2621
 
      desc->http_state = 0;  /* reset state (for next request) */
2622
 
      return http_eoh_message(desc);
2623
 
    }
2624
 
    h = 0;
2625
 
    while(n && !is_tspecial((unsigned char)*ptr)) {
2626
 
      int c = *ptr;
2627
 
      if (up) {
2628
 
        if (islower(c)) {
2629
 
          c = toupper(c);
2630
 
        }
2631
 
        up = 0;
2632
 
      }
2633
 
      else {
2634
 
        if (isupper(c))
2635
 
          c = tolower(c);
2636
 
        else if (c == '-')
2637
 
          up = 1;
2638
 
      }
2639
 
      *ptr = c;
2640
 
      hash_update(h, c);
2641
 
      ptr++;
2642
 
      n--;
2643
 
    }
2644
 
    if (*ptr != ':') {
2645
 
      /* Error case */
2646
 
      return -1;
2647
 
    }
2648
 
    name_ptr = buf;
2649
 
    name_len = (ptr - buf);
2650
 
    name = http_hash_lookup(name_ptr, name_len, h,
2651
 
                            http_hdr_hash, HTTP_HDR_HASH_SIZE);
2652
 
    ptr++;
2653
 
    n--;
2654
 
    /* Skip white space */
2655
 
    while(n && SP(ptr)) { ptr++; n--; }
2656
 
 
2657
 
    return http_header_message(desc, name, name_ptr, name_len,
2658
 
                               ptr, n);
2659
 
  }
2660
 
}
2661
 
#endif
 
2266
    http_response_inetdrv,
 
2267
    http_request_inetdrv,
 
2268
    http_eoh_inetdrv,
 
2269
    http_header_inetdrv,
 
2270
    http_error_inetdrv,
 
2271
    ssl_tls_inetdrv
 
2272
};
 
2273
 
2662
2274
 
2663
2275
/* 
2664
2276
** passive mode reply:
2666
2278
** NB: this is for TCP only;
2667
2279
** UDP and SCTP use inet_async_binary_data .
2668
2280
*/
2669
 
static int inet_async_data(inet_descriptor* desc, char* buf, int len)
 
2281
static int inet_async_data(inet_descriptor* desc, const char* buf, int len)
2670
2282
{
2671
2283
    unsigned int hsz = desc->hsz;
2672
2284
    ErlDrvTermData spec[20];
3303
2915
** active mode message:
3304
2916
**        {tcp, S, [H1,...Hsz | Data]}
3305
2917
*/
3306
 
static int tcp_message(inet_descriptor* desc, char* buf, int len)
 
2918
static int tcp_message(inet_descriptor* desc, const char* buf, int len)
3307
2919
{
3308
2920
    unsigned int hsz = desc->hsz;
3309
2921
    ErlDrvTermData spec[20];
3531
3143
    return driver_output_term(desc->port, spec, i);
3532
3144
}
3533
3145
 
3534
 
/*
3535
 
** The fcgi header is 8 bytes. After that comes the data and
3536
 
** possibly some padding.
3537
 
** return length of the header (and total length int plen)
3538
 
** return -1 when not enough bytes
3539
 
** return -2 when error
3540
 
*/
3541
 
#define FCGI_VERSION_1          1
3542
 
 
3543
 
struct fcgi_head {
3544
 
  unsigned char version;
3545
 
  unsigned char type;
3546
 
  unsigned char requestIdB1;
3547
 
  unsigned char requestIdB0;
3548
 
  unsigned char contentLengthB1;
3549
 
  unsigned char contentLengthB0;
3550
 
  unsigned char paddingLength;
3551
 
  unsigned char reserved;
3552
 
};
3553
 
 
3554
 
 
3555
 
#define CDR_MAGIC "GIOP"
3556
 
 
3557
 
struct cdr_head {
3558
 
    unsigned char magic[4];        /* 4 bytes must be 'GIOP' */
3559
 
    unsigned char major;           /* major version */ 
3560
 
    unsigned char minor;           /* minor version */
3561
 
    unsigned char flags;           /* bit 0: 0 == big endian, 1 == little endian 
3562
 
                                      bit 1: 1 == more fragments follow
3563
 
                                   */
3564
 
    unsigned char message_type;    /* message type ... */
3565
 
    unsigned char message_size[4]; /* size in (flags bit 0 byte order) */
3566
 
};
3567
 
 
3568
 
 
3569
 
#define TPKT_VRSN 3
3570
 
 
3571
 
struct tpkt_head {
3572
 
    unsigned char vrsn;             /* contains TPKT_VRSN */
3573
 
    unsigned char reserved;
3574
 
    unsigned char packet_length[2]; /* size incl header, big-endian (?) */
3575
 
};
3576
 
 
3577
3146
 
3578
3147
/* scan buffer for bit 7 */
3579
 
static void scanbit8(inet_descriptor* desc, char* buf, int len)
 
3148
static void scanbit8(inet_descriptor* desc, const char* buf, int len)
3580
3149
{
3581
3150
    int c;
3582
3151
 
3598
3167
static int tcp_reply_data(tcp_descriptor* desc, char* buf, int len)
3599
3168
{
3600
3169
    int code;
3601
 
 
3602
 
    /* adjust according to packet type */
3603
 
    switch(desc->inet.htype) {
3604
 
    case TCP_PB_1:  buf += 1; len -= 1; break;
3605
 
    case TCP_PB_2:  buf += 2; len -= 2; break;
3606
 
    case TCP_PB_4:  buf += 4; len -= 4; break;
3607
 
    case TCP_PB_FCGI:
3608
 
        len -= ((struct fcgi_head*)buf)->paddingLength;
3609
 
        break;
3610
 
    }
3611
 
 
3612
 
    scanbit8(INETP(desc), buf, len);
3613
 
 
3614
 
    if (desc->inet.deliver == INET_DELIVER_PORT)
3615
 
        code = inet_port_data(INETP(desc), buf, len);
3616
 
#ifdef USE_HTTP
3617
 
    else if ((desc->inet.htype == TCP_PB_HTTP) ||
3618
 
             (desc->inet.htype == TCP_PB_HTTPH)) {
3619
 
        if ((code = http_message(desc, buf, len)) < 0)
3620
 
            http_error_message(desc, buf, len);
3621
 
        code = 0;
3622
 
    }
3623
 
#endif    
3624
 
    else if (desc->inet.active == INET_PASSIVE)
3625
 
        return inet_async_data(INETP(desc), buf, len);
3626
 
    else
3627
 
        code = tcp_message(INETP(desc), buf, len);
 
3170
    const char* body = buf;
 
3171
    int bodylen = len;
 
3172
    
 
3173
    packet_get_body(desc->inet.htype, &body, &bodylen);
 
3174
 
 
3175
    scanbit8(INETP(desc), body, bodylen);
 
3176
 
 
3177
    if (desc->inet.deliver == INET_DELIVER_PORT) {
 
3178
        code = inet_port_data(INETP(desc), body, bodylen);
 
3179
    }
 
3180
    else if ((code=packet_parse(desc->inet.htype, buf, len,
 
3181
                                &desc->http_state, &packet_callbacks,
 
3182
                                desc)) == 0) {
 
3183
        /* No body parsing, return raw binary */
 
3184
        if (desc->inet.active == INET_PASSIVE)
 
3185
            return inet_async_data(INETP(desc), body, bodylen);
 
3186
        else
 
3187
            code = tcp_message(INETP(desc), body, bodylen);
 
3188
    }
3628
3189
 
3629
3190
    if (code < 0)
3630
3191
        return code;
3637
3198
tcp_reply_binary_data(tcp_descriptor* desc, ErlDrvBinary* bin, int offs, int len)
3638
3199
{
3639
3200
    int code;
3640
 
 
3641
 
    /* adjust according to packet type */
3642
 
    switch(desc->inet.htype) {
3643
 
    case TCP_PB_1:  offs += 1; len -= 1; break;
3644
 
    case TCP_PB_2:  offs += 2; len -= 2; break;
3645
 
    case TCP_PB_4:  offs += 4; len -= 4; break;
3646
 
    case TCP_PB_FCGI:
3647
 
        len -= ((struct fcgi_head*)(bin->orig_bytes+offs))->paddingLength;
3648
 
        break;
3649
 
    }
3650
 
 
3651
 
    scanbit8(INETP(desc), bin->orig_bytes+offs, len);
 
3201
    const char* buf = bin->orig_bytes + offs;
 
3202
    const char* body = buf;
 
3203
    int bodylen = len;
 
3204
 
 
3205
    packet_get_body(desc->inet.htype, &body, &bodylen);
 
3206
    offs = body - bin->orig_bytes; /* body offset now */
 
3207
 
 
3208
    scanbit8(INETP(desc), body, bodylen);
3652
3209
 
3653
3210
    if (desc->inet.deliver == INET_DELIVER_PORT)
3654
 
        code = inet_port_binary_data(INETP(desc), bin, offs, len);
3655
 
#ifdef USE_HTTP
3656
 
    else if ((desc->inet.htype == TCP_PB_HTTP) ||
3657
 
             (desc->inet.htype == TCP_PB_HTTPH)) {
3658
 
        if ((code = http_message(desc, bin->orig_bytes+offs, len)) < 0)
3659
 
            http_error_message(desc, bin->orig_bytes+offs, len);
3660
 
        code = 0;
 
3211
        code = inet_port_binary_data(INETP(desc), bin, offs, bodylen);
 
3212
    else if ((code=packet_parse(desc->inet.htype, buf, len, &desc->http_state,
 
3213
                                     &packet_callbacks,desc)) == 0) {
 
3214
        /* No body parsing, return raw data */
 
3215
        if (desc->inet.active == INET_PASSIVE)
 
3216
            return inet_async_binary_data(INETP(desc), 0, bin, offs, bodylen, NULL);
 
3217
        else
 
3218
            code = tcp_binary_message(INETP(desc), bin, offs, bodylen);
3661
3219
    }
3662
 
#endif
3663
 
    else if (desc->inet.active == INET_PASSIVE)
3664
 
        return inet_async_binary_data(INETP(desc), 0, bin, offs, len, NULL);
3665
 
    else
3666
 
        code = tcp_binary_message(INETP(desc), bin, offs, len);
3667
3220
    if (code < 0)
3668
3221
        return code;
3669
3222
    if (desc->inet.active == INET_ONCE)
3735
3288
#endif
3736
3289
}
3737
3290
 
3738
 
static int inet_init()
3739
 
{
3740
 
    if (!sock_init())
3741
 
        goto error;
3742
 
 
3743
 
    buffer_stack_pos = 0;
3744
 
 
3745
 
    erts_smp_spinlock_init(&inet_buffer_stack_lock, "inet_buffer_stack_lock");
3746
 
 
3747
 
    ASSERT(sizeof(struct in_addr) == 4);
3748
 
#   if defined(HAVE_IN6) && defined(AF_INET6)
3749
 
    ASSERT(sizeof(struct in6_addr) == 16);
3750
 
#   endif
3751
 
 
3752
 
#ifdef DEBUG
3753
 
    tot_buf_allocated = 0;
3754
 
    max_buf_allocated = 0;
3755
 
    tot_buf_stacked = 0;
3756
 
#endif
3757
 
    INIT_ATOM(ok);
3758
 
    INIT_ATOM(tcp);
3759
 
    INIT_ATOM(udp);
3760
 
    INIT_ATOM(error);
3761
 
    INIT_ATOM(inet_async);
3762
 
    INIT_ATOM(inet_reply);
3763
 
    INIT_ATOM(timeout);
3764
 
    INIT_ATOM(closed);
3765
 
    INIT_ATOM(tcp_closed);
3766
 
    INIT_ATOM(tcp_error);
3767
 
    INIT_ATOM(udp_error);
3768
 
    INIT_ATOM(empty_out_q);
3769
3291
#ifdef HAVE_SCTP
3770
 
    /* Check the size of SCTP AssocID -- currently both this driver and the
3771
 
       Erlang part require 32 bit: */
3772
 
    ASSERT(sizeof(sctp_assoc_t)==ASSOC_ID_LEN);
3773
 
    
 
3292
static void inet_init_sctp(void) {
3774
3293
    INIT_ATOM(sctp);
3775
3294
    INIT_ATOM(sctp_error);
3776
3295
    INIT_ATOM(true);
3881
3400
    ** INIT_ATOM(bound);
3882
3401
    ** INIT_ATOM(listen);
3883
3402
    */
 
3403
}
 
3404
#endif /* HAVE_SCTP */
 
3405
 
 
3406
static int inet_init()
 
3407
{
 
3408
    if (!sock_init())
 
3409
        goto error;
 
3410
 
 
3411
    buffer_stack_pos = 0;
 
3412
 
 
3413
    erts_smp_spinlock_init(&inet_buffer_stack_lock, "inet_buffer_stack_lock");
 
3414
 
 
3415
    ASSERT(sizeof(struct in_addr) == 4);
 
3416
#   if defined(HAVE_IN6) && defined(AF_INET6)
 
3417
    ASSERT(sizeof(struct in6_addr) == 16);
 
3418
#   endif
 
3419
 
 
3420
#ifdef DEBUG
 
3421
    tot_buf_allocated = 0;
 
3422
    max_buf_allocated = 0;
 
3423
    tot_buf_stacked = 0;
3884
3424
#endif
3885
 
    
 
3425
    INIT_ATOM(ok);
 
3426
    INIT_ATOM(tcp);
 
3427
    INIT_ATOM(udp);
 
3428
    INIT_ATOM(error);
 
3429
    INIT_ATOM(inet_async);
 
3430
    INIT_ATOM(inet_reply);
 
3431
    INIT_ATOM(timeout);
 
3432
    INIT_ATOM(closed);
 
3433
    INIT_ATOM(tcp_closed);
 
3434
    INIT_ATOM(tcp_error);
 
3435
    INIT_ATOM(udp_error);
 
3436
    INIT_ATOM(empty_out_q);
 
3437
    INIT_ATOM(ssl_tls);
 
3438
 
 
3439
    INIT_ATOM(http_eoh);
 
3440
    INIT_ATOM(http_header);
 
3441
    INIT_ATOM(http_request);
 
3442
    INIT_ATOM(http_response);
 
3443
    INIT_ATOM(http_error);
 
3444
    INIT_ATOM(abs_path);
 
3445
    INIT_ATOM(absoluteURI);
 
3446
    am_star = driver_mk_atom("*");
 
3447
    INIT_ATOM(undefined);
 
3448
    INIT_ATOM(http);
 
3449
    INIT_ATOM(https);
 
3450
    INIT_ATOM(scheme);
 
3451
 
3886
3452
    /* add TCP, UDP and SCTP drivers */
3887
3453
#ifdef _OSE_
3888
3454
    add_ose_tcp_drv_entry(&tcp_inet_driver_entry);
3891
3457
    add_driver_entry(&tcp_inet_driver_entry);
3892
3458
    add_driver_entry(&udp_inet_driver_entry);
3893
3459
#  ifdef HAVE_SCTP
3894
 
    add_driver_entry(&sctp_inet_driver_entry);
 
3460
    /* Check the size of SCTP AssocID -- currently both this driver and the
 
3461
       Erlang part require 32 bit: */
 
3462
    ASSERT(sizeof(sctp_assoc_t)==ASSOC_ID_LEN);
 
3463
#   ifndef LIBSCTP
 
3464
#     error LIBSCTP not defined
 
3465
#   endif
 
3466
    if (erts_sys_ddll_open_noext(STRINGIFY(LIBSCTP), &h_libsctp) == 0) {
 
3467
        void *ptr;
 
3468
        if (erts_sys_ddll_sym(h_libsctp, "sctp_bindx", &ptr) == 0) {
 
3469
            p_sctp_bindx = ptr;
 
3470
            inet_init_sctp();
 
3471
            add_driver_entry(&sctp_inet_driver_entry);
 
3472
        }
 
3473
    }
3895
3474
#  endif
3896
3475
#endif /* _OSE_ */
3897
3476
    /* remove the dummy inet driver */
3898
3477
    remove_driver_entry(&inet_driver_entry);
3899
 
#ifdef USE_HTTP
3900
 
    http_init();
3901
 
#endif
3902
3478
    return 0;
3903
3479
 
3904
3480
 error:
4932
4508
    int ival;
4933
4509
    char* arg_ptr;
4934
4510
    int arg_sz;
4935
 
    int old_htype = desc->htype;
 
4511
    enum PacketParseType old_htype = desc->htype;
4936
4512
    int old_active = desc->active;
4937
4513
    int propagate = 0; /* Set to 1 if failure to set this option
4938
4514
                          should be propagated to erlang (not all 
7494
7070
    desc->i_remain = 0;
7495
7071
    desc->i_bufsz = 0;
7496
7072
    desc->tcp_add_flags = 0;
7497
 
#ifdef USE_HTTP
7498
7073
    desc->http_state = 0;
7499
 
#endif
7500
7074
    desc->mtd = NULL;
7501
7075
    desc->multi_first = desc->multi_last = NULL;
7502
7076
    DEBUGF(("tcp_inet_start(%ld) }\r\n", (long)port));
7690
7264
                             buf, &len) == NULL)
7691
7265
            return ctl_error(EINVAL, rbuf, rsize);
7692
7266
        
7693
 
        sock_select(INETP(desc), FD_CONNECT, 1);
7694
7267
        code = sock_connect(desc->inet.s, 
7695
7268
                            (struct sockaddr*) &desc->inet.remote, len);
7696
7269
        if ((code == SOCKET_ERROR) && 
7697
7270
                ((sock_errno() == ERRNO_BLOCK) ||  /* Winsock2 */
7698
7271
                 (sock_errno() == EINPROGRESS))) {      /* Unix & OSE!! */
 
7272
          sock_select(INETP(desc), FD_CONNECT, 1);
7699
7273
            desc->inet.state = TCP_STATE_CONNECTING;
7700
7274
            if (timeout != INET_INFINITY)
7701
7275
                driver_set_timer(desc->inet.port, timeout);
7702
7276
            enq_async(INETP(desc), tbuf, INET_REQ_CONNECT);
7703
7277
        }
7704
7278
        else if (code == 0) { /* ok we are connected */
7705
 
            sock_select(INETP(desc), FD_CONNECT, 0);
7706
7279
            desc->inet.state = TCP_STATE_CONNECTED;
7707
7280
            if (desc->inet.active)
7708
7281
                sock_select(INETP(desc), (FD_READ|FD_CLOSE), 1);
7710
7283
            async_ok(INETP(desc));
7711
7284
        }
7712
7285
        else {
7713
 
            sock_select(INETP(desc), FD_CONNECT, 0);
7714
7286
            return ctl_error(sock_errno(), rbuf, rsize);
7715
7287
        }
7716
7288
        return ctl_reply(INET_REP_OK, tbuf, 2, rbuf, rsize);
8015
7587
    DEBUGF(("tcp_inet_commandv(%ld) }\r\n", (long)desc->inet.port)); 
8016
7588
}
8017
7589
 
 
7590
static void tcp_inet_flush(ErlDrvData e)
 
7591
{
 
7592
    tcp_descriptor* desc = (tcp_descriptor*)e;
 
7593
    if (!(desc->inet.event_mask & FD_WRITE)) {
 
7594
        /* Discard send queue to avoid hanging port (OTP-7615) */
 
7595
        tcp_clear_output(desc);
 
7596
    }
 
7597
}
 
7598
 
8018
7599
static void tcp_inet_process_exit(ErlDrvData e, ErlDrvMonitor *monitorp) 
8019
7600
{
8020
7601
    tcp_descriptor* desc = (tcp_descriptor*)e;
8074
7655
        /* passive mode do not terminate port ! */
8075
7656
        tcp_clear_input(desc);
8076
7657
        if (desc->inet.exitf) {
 
7658
            tcp_clear_output(desc);
8077
7659
            desc_close(INETP(desc));
8078
7660
        } else {
8079
7661
            desc_close_read(INETP(desc));
8157
7739
    int nfill = (desc->i_ptr - desc->i_buf->orig_bytes); /* filled */
8158
7740
    int nsz   = desc->i_bufsz - nfill;                   /* remain */
8159
7741
    int n = desc->i_ptr - ptr;  /* number of bytes read */
8160
 
    int plen;
8161
 
    int hlen;
 
7742
    int tlen;
8162
7743
 
8163
7744
    DEBUGF(("tcp_remain(%ld): s=%d, n=%d, nfill=%d nsz=%d\r\n", 
8164
7745
            (long)desc->inet.port, desc->inet.s, n, nfill, nsz));
8165
7746
 
8166
 
    switch(desc->inet.htype) {
8167
 
    case TCP_PB_RAW:
8168
 
        if (n == 0) goto more;
8169
 
        else {
8170
 
            *len = n;
8171
 
            DEBUGF((" => nothing remain packet=%d\r\n", n));        
8172
 
            return 0;  /* deliver */
8173
 
        }
8174
 
 
8175
 
    case TCP_PB_1:
8176
 
        /* TCP_PB_1:    [L0 | Data] */
8177
 
        hlen = 1;
8178
 
        if (n < hlen) goto more;
8179
 
        plen = get_int8(ptr);
8180
 
        goto remain;
8181
 
 
8182
 
    case TCP_PB_2:
8183
 
        /* TCP_PB_2:    [L1,L0 | Data] */
8184
 
        hlen = 2;
8185
 
        if (n < hlen) goto more;
8186
 
        plen = get_int16(ptr);
8187
 
        goto remain;
8188
 
 
8189
 
    case TCP_PB_4:
8190
 
        /* TCP_PB_4:    [L3,L2,L1,L0 | Data] */
8191
 
        hlen = 4;
8192
 
        if (n < hlen) goto more;
8193
 
        plen = get_int32(ptr);
8194
 
        goto remain;
8195
 
 
8196
 
    case TCP_PB_RM:
8197
 
        /* TCP_PB_RM:    [L3,L2,L1,L0 | Data] 
8198
 
         ** where MSB (bit) is used to signal end of record
8199
 
         */
8200
 
        hlen = 4;
8201
 
        if (n < hlen) goto more;
8202
 
        plen = get_int32(ptr) & 0x7fffffff;
8203
 
        goto remain;
8204
 
 
8205
 
    case TCP_PB_LINE_LF: {
8206
 
        /* TCP_PB_LINE_LF:  [Data ... \n]  */
8207
 
        char* ptr2;
8208
 
        if  ((ptr2 = memchr(ptr, '\n', n)) == NULL) {
8209
 
            if ((nsz == 0) && (nfill == n)) { /* buffer full */
8210
 
                *len = n;
8211
 
                DEBUGF((" => line buffer full (no NL)=%d\r\n", n));
8212
 
                return 0;
8213
 
            }
8214
 
            goto more;
8215
 
        }
8216
 
        else {
8217
 
            *len = (ptr2 - ptr) + 1;  /* include newline */
8218
 
            DEBUGF((" => nothing remain packet=%d\r\n", *len));
8219
 
            return 0;
8220
 
        }
8221
 
    }
8222
 
 
8223
 
    case TCP_PB_ASN1: {
8224
 
        /* TCP_PB_ASN1: handles long (4 bytes) or short length format */
8225
 
        char* tptr = ptr;
8226
 
        int length;
8227
 
        int nn = n;
8228
 
 
8229
 
        if (n < 2) goto more;
8230
 
        nn--;
8231
 
        if ((*tptr++ & 0x1f) == 0x1f) { /* Long tag format */
8232
 
            while(nn && ((*tptr & 0x80) == 0x80)) {
8233
 
                tptr++;
8234
 
                nn--;
8235
 
            }
8236
 
            if (nn < 2) goto more;
8237
 
            tptr++;
8238
 
            nn--;
8239
 
        }
8240
 
 
8241
 
        /* tptr now point to length field and n characters remain */
8242
 
        length = *tptr & 0x7f;
8243
 
        if ((*tptr & 0x80) == 0x80) {   /* Long length format */
8244
 
            tptr++;
8245
 
            nn--;
8246
 
            if (nn < length) goto more;
8247
 
            switch(length) {
8248
 
            case 0: plen = 0; break;
8249
 
            case 1: plen = get_int8(tptr);  tptr += 1; break;
8250
 
            case 2: plen = get_int16(tptr); tptr += 2; break;
8251
 
            case 3: plen = get_int24(tptr); tptr += 3; break;
8252
 
            case 4: plen = get_int32(tptr); tptr += 4; break;
8253
 
            default: goto error; /* error */
8254
 
            }
8255
 
        }
8256
 
        else {
8257
 
            tptr++;
8258
 
            plen = length;
8259
 
        }
8260
 
        hlen = (tptr-ptr);
8261
 
        goto remain;
8262
 
    }
8263
 
 
8264
 
 
8265
 
    case TCP_PB_CDR: {
8266
 
        struct cdr_head* hp;
8267
 
        hlen = sizeof(struct cdr_head);
8268
 
        if (n < hlen) goto more;
8269
 
        hp = (struct cdr_head*) ptr;
8270
 
        if (sys_memcmp(hp->magic, CDR_MAGIC, 4) != 0)
8271
 
            goto error;
8272
 
        if (hp->flags & 0x01) /* Byte ordering flag */
8273
 
            plen = get_little_int32(hp->message_size);
8274
 
        else
8275
 
            plen = get_int32(hp->message_size);
8276
 
        goto remain;
8277
 
    }
8278
 
 
8279
 
    case TCP_PB_FCGI: {
8280
 
        struct fcgi_head* hp;
8281
 
        hlen = sizeof(struct fcgi_head);
8282
 
        if (n < hlen) goto more;
8283
 
        hp = (struct fcgi_head*) ptr;
8284
 
        if (hp->version != FCGI_VERSION_1)
8285
 
            goto error;                 /* ERROR, unknown header version */
8286
 
        plen = ((hp->contentLengthB1 << 8) | hp->contentLengthB0)
8287
 
            + hp->paddingLength;
8288
 
        goto remain;
8289
 
    }
8290
 
#ifdef USE_HTTP
8291
 
    case TCP_PB_HTTPH:
8292
 
        desc->http_state = 1;
8293
 
    case TCP_PB_HTTP: {
8294
 
        /* TCP_PB_HTTP:  data \r\n(SP data\r\n)*  */
8295
 
        plen = n;
8296
 
        if (((plen == 1) && NL(ptr)) || ((plen == 2) && CRNL(ptr)))
8297
 
            goto done;
8298
 
        else {
8299
 
            char* ptr1 = ptr;
8300
 
            int   len = plen;
8301
 
 
8302
 
            while(1) {
8303
 
              char* ptr2 = memchr(ptr1, '\n', len);
8304
 
 
8305
 
              if  (ptr2 == NULL) {
8306
 
                  if ((nsz == 0) && (nfill == n)) { /* buffer full */
8307
 
                      plen = n;
8308
 
                      goto done;
8309
 
                  }
8310
 
                  goto more;
8311
 
              }
8312
 
              else {
8313
 
                  plen = (ptr2 - ptr) + 1;
8314
 
 
8315
 
                  if (desc->http_state == 0) 
8316
 
                      goto done;
8317
 
                
8318
 
                  if (plen < n) {
8319
 
                      if (SP(ptr2+1)) {
8320
 
                          ptr1 = ptr2+1;
8321
 
                          len = n - plen;
8322
 
                      }
8323
 
                      else
8324
 
                          goto done;
8325
 
                  }
8326
 
                  else
8327
 
                      goto more;
8328
 
              }
8329
 
            }
8330
 
        }
8331
 
    }
8332
 
#endif
8333
 
    case TCP_PB_TPKT: {
8334
 
        struct tpkt_head* hp;
8335
 
        hlen = sizeof(struct tpkt_head);
8336
 
        if (n < hlen) 
8337
 
            goto more;
8338
 
        hp = (struct tpkt_head*) ptr;
8339
 
        if (hp->vrsn == TPKT_VRSN) {
8340
 
            plen = get_int16(hp->packet_length) - hlen;
8341
 
            if (plen < 0)
8342
 
                goto error;
8343
 
        } else
8344
 
            goto error;
8345
 
        goto remain;
8346
 
    }
8347
 
 
8348
 
    default:  /* this can not occure (make compiler happy) */
8349
 
        DEBUGF((" => case error\r\n"));
8350
 
        return -1;
8351
 
    }
8352
 
 
8353
 
 done: {
8354
 
      *len = plen;
8355
 
      DEBUGF((" => nothing remain packet=%d\r\n", plen));
8356
 
      return 0;
8357
 
    }
8358
 
 
8359
 
 remain: {
8360
 
     int tlen, remain;
8361
 
     if (desc->inet.psize != 0 && 
8362
 
         ((unsigned int)plen) > desc->inet.psize) goto error;
8363
 
     tlen = plen + hlen;
8364
 
     remain = tlen - n;
8365
 
     if (remain <= 0) {
8366
 
         *len = tlen;
8367
 
         DEBUGF((" => nothing remain packet=%d\r\n", tlen));
8368
 
         return 0;
8369
 
     }
8370
 
     else {
8371
 
         if (tcp_expand_buffer(desc, tlen) < 0)
8372
 
             return -1;
8373
 
         DEBUGF((" => remain=%d\r\n", remain));
8374
 
         *len = remain;
8375
 
         return remain;
8376
 
     }
8377
 
 }
8378
 
 
8379
 
 more:
8380
 
    *len = 0;
8381
 
    if (nsz == 0) {
8382
 
        if (nfill == n)
8383
 
            goto error;
8384
 
        DEBUGF((" => restart more=%d\r\n", nfill - n));
8385
 
        return nfill - n;
8386
 
    }
8387
 
    else {
8388
 
        DEBUGF((" => more=%d \r\n", nsz));
8389
 
        return nsz;
8390
 
    }
8391
 
 
8392
 
 error:
 
7747
    tlen = packet_get_length(desc->inet.htype, ptr, n, 
 
7748
                             desc->inet.psize, desc->i_bufsz,
 
7749
                             &desc->http_state);
 
7750
    if (tlen > 0) {
 
7751
        if (tlen <= n) { /* got a packet */
 
7752
            *len = tlen;
 
7753
            DEBUGF((" => nothing remain packet=%d\r\n", tlen));
 
7754
            return 0;
 
7755
        }
 
7756
        else { /* need known more */
 
7757
            if (tcp_expand_buffer(desc, tlen) < 0)
 
7758
                return -1;
 
7759
            *len = tlen - n;
 
7760
            DEBUGF((" => remain=%d\r\n", *len));
 
7761
            return *len;
 
7762
        }
 
7763
    }
 
7764
    else if (tlen == 0) { /* need unknown more */
 
7765
        *len = 0;
 
7766
        if (nsz == 0) {
 
7767
            if (nfill == n)
 
7768
                goto error;
 
7769
            DEBUGF((" => restart more=%d\r\n", nfill - n));
 
7770
            return nfill - n;
 
7771
        }
 
7772
        else {
 
7773
            DEBUGF((" => more=%d \r\n", nsz));
 
7774
            return nsz;
 
7775
        }           
 
7776
    }
 
7777
 
 
7778
error:
8393
7779
    DEBUGF((" => packet error\r\n"));
8394
7780
    return -1;
8395
7781
}
8981
8367
    ErlDrvPort ix = desc->inet.port;
8982
8368
    int len = ev->size;
8983
8369
 
8984
 
    switch(desc->inet.htype) {
8985
 
    case TCP_PB_1: 
8986
 
        put_int8(len, buf);
8987
 
        h_len = 1;
8988
 
        break;
8989
 
    case TCP_PB_2: 
8990
 
        put_int16(len, buf);
8991
 
        h_len = 2; 
8992
 
        break;
8993
 
    case TCP_PB_4: 
8994
 
        put_int32(len, buf);
8995
 
        h_len = 4; 
8996
 
        break;
8997
 
    default:
8998
 
        if (len == 0)
8999
 
            return 0;
9000
 
        h_len = 0;
9001
 
        break;
9002
 
    }
 
8370
     switch(desc->inet.htype) {
 
8371
     case TCP_PB_1:
 
8372
         put_int8(len, buf);
 
8373
         h_len = 1;
 
8374
         break;
 
8375
     case TCP_PB_2:
 
8376
         put_int16(len, buf);
 
8377
         h_len = 2;
 
8378
         break;
 
8379
     case TCP_PB_4:
 
8380
         put_int32(len, buf);
 
8381
         h_len = 4;
 
8382
         break;
 
8383
     default:
 
8384
         if (len == 0)
 
8385
             return 0;
 
8386
         h_len = 0;
 
8387
         break;
 
8388
     }
9003
8389
 
9004
8390
    inet_output_count(INETP(desc), len+h_len);
9005
8391
 
9611
8997
            rflag = add_flag ? SCTP_BINDX_ADD_ADDR : SCTP_BINDX_REM_ADDR;
9612
8998
 
9613
8999
            /* Invoke the call: */
9614
 
            if (sctp_bindx(desc->s, addrs, n, rflag) < 0)
 
9000
            if (p_sctp_bindx(desc->s, addrs, n, rflag) < 0)
9615
9001
                return ctl_error(sock_errno(), rbuf, rsize);
9616
9002
 
9617
9003
            desc->state = INET_STATE_BOUND;