PageRenderTime 79ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 1ms

/EtherCard/ip_arp_udp_tcp.cpp

https://github.com/robomotic/Hardware
C++ | 841 lines | 779 code | 46 blank | 16 comment | 84 complexity | 9894fad939c5f5c8ee47b70de0d1903c MD5 | raw file
  1. // IP, Arp, UDP and TCP functions.
  2. // Author: Guido Socher
  3. // Copyright: GPL V2
  4. //
  5. // The TCP implementation uses some size optimisations which are valid
  6. // only if all data can be sent in one single packet. This is however
  7. // not a big limitation for a microcontroller as you will anyhow use
  8. // small web-pages. The web server must send the entire web page in one
  9. // packet. The client "web browser" as implemented here can also receive
  10. // large pages.
  11. //
  12. // Mods bij jcw, 2010-05-20
  13. #include <avr/pgmspace.h>
  14. #include "net.h"
  15. #include "enc28j60.h"
  16. #include "ip_config.h"
  17. #include <WProgram.h>
  18. static byte wwwport_l=80; // server port
  19. static byte wwwport_h; // Note: never use same as TCPCLIENT_SRC_PORT_H
  20. static byte tcpclient_src_port_l=1;
  21. static byte tcp_fd; // a file descriptor, will be encoded into the port
  22. static byte tcpsrvip[4];
  23. static byte tcp_client_state;
  24. static byte tcp_client_port_h;
  25. static byte tcp_client_port_l;
  26. static byte (*client_tcp_result_callback)(byte,byte,uint16_t,uint16_t);
  27. static uint16_t (*client_tcp_datafill_callback)(byte);
  28. #define TCPCLIENT_SRC_PORT_H 11
  29. // #define TCP_client 1
  30. static byte www_fd;
  31. static byte browsertype; // 0 = get, 1 = post
  32. static void (*client_browser_callback)(byte,uint16_t,uint16_t);
  33. static prog_char *client_additionalheaderline;
  34. static char *client_postval;
  35. static prog_char *client_urlbuf;
  36. static char *client_urlbuf_var;
  37. static prog_char *client_hoststr;
  38. static byte *bufptr; // ugly workaround for backward compatibility
  39. static void (*icmp_callback)(byte *ip);
  40. static int16_t delaycnt=1;
  41. static byte gwip[4];
  42. static byte gwmacaddr[6];
  43. static byte waitgwmac; // 0=wait, 1=first req no anser, 2=have gwmac, 4=refeshing but have gw mac, 8=accept an arp reply
  44. #define WGW_INITIAL_ARP 1
  45. #define WGW_HAVE_GW_MAC 2
  46. #define WGW_REFRESHING 4
  47. #define WGW_ACCEPT_ARP_REPLY 8
  48. static byte macaddr[6];
  49. static byte ipaddr[4];
  50. static uint16_t info_data_len;
  51. static byte seqnum=0xa; // my initial tcp sequence number
  52. #define CLIENTMSS 550
  53. #define TCP_DATA_START ((uint16_t)TCP_SRC_PORT_H_P+(buf[TCP_HEADER_LEN_P]>>4)*4)
  54. const char arpreqhdr[] PROGMEM = { 0,1,8,0,6,4,0,1 };
  55. const char iphdr[] PROGMEM = { 0x45,0,0,0x82,0,0,0x40,0,0x20 };
  56. const char ntpreqhdr[] PROGMEM = { 0xE3,0,4,0xFA,0,1,0,0,0,1 };
  57. static uint16_t checksum(byte *buf, uint16_t len,byte type){
  58. uint32_t sum = type==1 ? IP_PROTO_UDP_V+len-8 :
  59. type==2 ? IP_PROTO_TCP_V+len-8 : 0;
  60. while(len >1){
  61. sum += 0xFFFF & (((uint32_t)*buf<<8)|*(buf+1));
  62. buf+=2;
  63. len-=2;
  64. }
  65. if (len)
  66. sum += ((uint32_t)*buf)<<8;
  67. while (sum>>16)
  68. sum = (sum & 0xFFFF)+(sum >> 16);
  69. return (uint16_t) sum ^ 0xFFFF;
  70. }
  71. void init_ip_arp_udp_tcp(byte *mymac,byte *myip,uint16_t port){
  72. wwwport_h=(port>>8);
  73. wwwport_l=(port);
  74. byte i=0;
  75. while(i<4){
  76. ipaddr[i]=myip[i];
  77. i++;
  78. }
  79. i=0;
  80. while(i<6){
  81. macaddr[i]=mymac[i];
  82. i++;
  83. }
  84. }
  85. static byte check_ip_message_is_from(byte *buf,byte *ip) {
  86. byte i=0;
  87. while(i<4){
  88. if (buf[IP_SRC_P+i]!=ip[i])
  89. return 0;
  90. i++;
  91. }
  92. return 1;
  93. }
  94. static byte eth_type_is_arp_and_my_ip(byte *buf,uint16_t len){
  95. if (len<41)
  96. return 0;
  97. if (buf[ETH_TYPE_H_P] != ETHTYPE_ARP_H_V ||
  98. buf[ETH_TYPE_L_P] != ETHTYPE_ARP_L_V)
  99. return 0;
  100. byte i=0;
  101. while(i<4){
  102. if (buf[ETH_ARP_DST_IP_P+i] != ipaddr[i])
  103. return 0;
  104. i++;
  105. }
  106. return 1;
  107. }
  108. static byte eth_type_is_ip_and_my_ip(byte *buf,uint16_t len){
  109. if (len<42)
  110. return 0;
  111. if (buf[ETH_TYPE_H_P]!=ETHTYPE_IP_H_V ||
  112. buf[ETH_TYPE_L_P]!=ETHTYPE_IP_L_V)
  113. return 0;
  114. if (buf[IP_HEADER_LEN_VER_P]!=0x45)
  115. return 0;
  116. byte i=0;
  117. while(i<4){
  118. if (buf[IP_DST_P+i]!=ipaddr[i])
  119. return 0;
  120. i++;
  121. }
  122. return 1;
  123. }
  124. static void make_eth(byte *buf) {
  125. byte i=0;
  126. while(i<6){
  127. buf[ETH_DST_MAC +i]=buf[ETH_SRC_MAC +i];
  128. buf[ETH_SRC_MAC +i]=macaddr[i];
  129. i++;
  130. }
  131. }
  132. static void fill_ip_hdr_checksum(byte *buf) {
  133. buf[IP_CHECKSUM_P]=0;
  134. buf[IP_CHECKSUM_P+1]=0;
  135. buf[IP_FLAGS_P]=0x40; // don't fragment
  136. buf[IP_FLAGS_P+1]=0; // fragement offset
  137. buf[IP_TTL_P]=64; // ttl
  138. uint16_t ck=checksum(&buf[IP_P], IP_HEADER_LEN,0);
  139. buf[IP_CHECKSUM_P]=ck>>8;
  140. buf[IP_CHECKSUM_P+1]=ck;
  141. }
  142. static void make_ip(byte *buf) {
  143. byte i=0;
  144. while(i<4){
  145. buf[IP_DST_P+i]=buf[IP_SRC_P+i];
  146. buf[IP_SRC_P+i]=ipaddr[i];
  147. i++;
  148. }
  149. fill_ip_hdr_checksum(buf);
  150. }
  151. static void step_seq(byte *buf,uint16_t rel_ack_num,byte cp_seq) {
  152. byte i;
  153. byte tseq;
  154. i=4;
  155. while(i>0){
  156. rel_ack_num=buf[TCP_SEQ_H_P+i-1]+rel_ack_num;
  157. tseq=buf[TCP_SEQACK_H_P+i-1];
  158. buf[TCP_SEQACK_H_P+i-1]=0xff&rel_ack_num;
  159. if (cp_seq)
  160. buf[TCP_SEQ_H_P+i-1]=tseq;
  161. else
  162. buf[TCP_SEQ_H_P+i-1]= 0; // some preset value
  163. rel_ack_num=rel_ack_num>>8;
  164. i--;
  165. }
  166. }
  167. static void make_tcphead(byte *buf,uint16_t rel_ack_num,byte cp_seq) {
  168. byte i;
  169. i=buf[TCP_DST_PORT_H_P];
  170. buf[TCP_DST_PORT_H_P]=buf[TCP_SRC_PORT_H_P];
  171. buf[TCP_SRC_PORT_H_P]=i;
  172. i=buf[TCP_DST_PORT_L_P];
  173. buf[TCP_DST_PORT_L_P]=buf[TCP_SRC_PORT_L_P];
  174. buf[TCP_SRC_PORT_L_P]=i;
  175. step_seq(buf,rel_ack_num,cp_seq);
  176. buf[TCP_CHECKSUM_H_P]=0;
  177. buf[TCP_CHECKSUM_L_P]=0;
  178. buf[TCP_HEADER_LEN_P]=0x50;
  179. }
  180. void make_arp_answer_from_request(byte *buf) {
  181. make_eth(buf);
  182. buf[ETH_ARP_OPCODE_H_P]=ETH_ARP_OPCODE_REPLY_H_V;
  183. buf[ETH_ARP_OPCODE_L_P]=ETH_ARP_OPCODE_REPLY_L_V;
  184. byte i=0;
  185. while(i<6){
  186. buf[ETH_ARP_DST_MAC_P+i]=buf[ETH_ARP_SRC_MAC_P+i];
  187. buf[ETH_ARP_SRC_MAC_P+i]=macaddr[i];
  188. i++;
  189. }
  190. i=0;
  191. while(i<4){
  192. buf[ETH_ARP_DST_IP_P+i]=buf[ETH_ARP_SRC_IP_P+i];
  193. buf[ETH_ARP_SRC_IP_P+i]=ipaddr[i];
  194. i++;
  195. }
  196. enc28j60PacketSend(42,buf);
  197. }
  198. void make_echo_reply_from_request(byte *buf,uint16_t len) {
  199. make_eth(buf);
  200. make_ip(buf);
  201. buf[ICMP_TYPE_P]=ICMP_TYPE_ECHOREPLY_V;
  202. if (buf[ICMP_CHECKSUM_P] > (0xff-0x08))
  203. buf[ICMP_CHECKSUM_P+1]++;
  204. buf[ICMP_CHECKSUM_P]+=0x08;
  205. //
  206. enc28j60PacketSend(len,buf);
  207. }
  208. void make_udp_reply_from_request(byte *buf,char *data,byte datalen,uint16_t port) {
  209. make_eth(buf);
  210. if (datalen>220)
  211. datalen=220;
  212. buf[IP_TOTLEN_H_P]=0;
  213. buf[IP_TOTLEN_L_P]=IP_HEADER_LEN+UDP_HEADER_LEN+datalen;
  214. make_ip(buf);
  215. buf[UDP_DST_PORT_H_P]=buf[UDP_SRC_PORT_H_P];
  216. buf[UDP_DST_PORT_L_P]= buf[UDP_SRC_PORT_L_P];
  217. buf[UDP_SRC_PORT_H_P]=port>>8;
  218. buf[UDP_SRC_PORT_L_P]=port;
  219. buf[UDP_LEN_H_P]=0;
  220. buf[UDP_LEN_L_P]=UDP_HEADER_LEN+datalen;
  221. buf[UDP_CHECKSUM_H_P]=0;
  222. buf[UDP_CHECKSUM_L_P]=0;
  223. byte i=0;
  224. while(i<datalen){
  225. buf[UDP_DATA_P+i]=data[i];
  226. i++;
  227. }
  228. uint16_t ck=checksum(&buf[IP_SRC_P], 16 + datalen,1);
  229. buf[UDP_CHECKSUM_H_P]=ck>>8;
  230. buf[UDP_CHECKSUM_L_P]=ck;
  231. enc28j60PacketSend(UDP_HEADER_LEN+IP_HEADER_LEN+ETH_HEADER_LEN+datalen,buf);
  232. }
  233. static void make_tcp_synack_from_syn(byte *buf) {
  234. make_eth(buf);
  235. buf[IP_TOTLEN_H_P]=0;
  236. buf[IP_TOTLEN_L_P]=IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+4;
  237. make_ip(buf);
  238. buf[TCP_FLAGS_P]=TCP_FLAGS_SYNACK_V;
  239. make_tcphead(buf,1,0);
  240. buf[TCP_SEQ_H_P+0]= 0;
  241. buf[TCP_SEQ_H_P+1]= 0;
  242. buf[TCP_SEQ_H_P+2]= seqnum;
  243. buf[TCP_SEQ_H_P+3]= 0;
  244. seqnum+=3;
  245. buf[TCP_OPTIONS_P]=2;
  246. buf[TCP_OPTIONS_P+1]=4;
  247. buf[TCP_OPTIONS_P+2]=0x05;
  248. buf[TCP_OPTIONS_P+3]=0x0;
  249. buf[TCP_HEADER_LEN_P]=0x60;
  250. buf[TCP_WIN_SIZE]=0x5; // 1400=0x578
  251. buf[TCP_WIN_SIZE+1]=0x78;
  252. uint16_t ck=checksum(&buf[IP_SRC_P], 8+TCP_HEADER_LEN_PLAIN+4,2);
  253. buf[TCP_CHECKSUM_H_P]=ck>>8;
  254. buf[TCP_CHECKSUM_L_P]=ck;
  255. enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+4+ETH_HEADER_LEN,buf);
  256. }
  257. static uint16_t get_tcp_data_len(byte *buf) {
  258. int16_t i = (((int16_t)buf[IP_TOTLEN_H_P])<<8)|buf[IP_TOTLEN_L_P];
  259. i-=IP_HEADER_LEN;
  260. i-=(buf[TCP_HEADER_LEN_P]>>4)*4; // generate len in bytes;
  261. if (i<=0)
  262. i=0;
  263. return (uint16_t)i;
  264. }
  265. uint16_t fill_tcp_data_p(byte *buf,uint16_t pos, const prog_char *progmem_s) {
  266. char c;
  267. while ((c = pgm_read_byte(progmem_s++)))
  268. buf[TCP_CHECKSUM_L_P+3+pos++]=c;
  269. return pos;
  270. }
  271. uint16_t fill_tcp_data_len(byte *buf,uint16_t pos, const byte *s, byte len) {
  272. while (len--)
  273. buf[TCP_CHECKSUM_L_P+3+pos++]=*s++;
  274. return pos;
  275. }
  276. uint16_t fill_tcp_data(byte *buf,uint16_t pos, const char *s) {
  277. return fill_tcp_data_len(buf,pos,(byte*)s,strlen(s));
  278. }
  279. static void make_tcp_ack_from_any(byte *buf,int16_t datlentoack,byte addflags) {
  280. uint16_t j;
  281. make_eth(buf);
  282. buf[TCP_FLAGS_P]=TCP_FLAGS_ACK_V|addflags;
  283. if (addflags!=TCP_FLAGS_RST_V && datlentoack==0)
  284. datlentoack=1;
  285. make_tcphead(buf,datlentoack,1); // no options
  286. j=IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN;
  287. buf[IP_TOTLEN_H_P]=j>>8;
  288. buf[IP_TOTLEN_L_P]=j;
  289. make_ip(buf);
  290. buf[TCP_WIN_SIZE]=0x4; // 1024=0x400, 1280=0x500 2048=0x800 768=0x300
  291. buf[TCP_WIN_SIZE+1]=0;
  292. j=checksum(&buf[IP_SRC_P], 8+TCP_HEADER_LEN_PLAIN,2);
  293. buf[TCP_CHECKSUM_H_P]=j>>8;
  294. buf[TCP_CHECKSUM_L_P]=j;
  295. enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+ETH_HEADER_LEN,buf);
  296. }
  297. static void make_tcp_ack_with_data_noflags(byte *buf,uint16_t dlen) {
  298. uint16_t j = IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+dlen;
  299. buf[IP_TOTLEN_H_P]=j>>8;
  300. buf[IP_TOTLEN_L_P]=j;
  301. fill_ip_hdr_checksum(buf);
  302. buf[TCP_CHECKSUM_H_P]=0;
  303. buf[TCP_CHECKSUM_L_P]=0;
  304. j=checksum(&buf[IP_SRC_P], 8+TCP_HEADER_LEN_PLAIN+dlen,2);
  305. buf[TCP_CHECKSUM_H_P]=j>>8;
  306. buf[TCP_CHECKSUM_L_P]=j;
  307. enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+dlen+ETH_HEADER_LEN,buf);
  308. }
  309. void www_server_reply(byte *buf,uint16_t dlen) {
  310. make_tcp_ack_from_any(buf,info_data_len,0); // send ack for http get
  311. buf[TCP_FLAGS_P]=TCP_FLAGS_ACK_V|TCP_FLAGS_PUSH_V|TCP_FLAGS_FIN_V;
  312. make_tcp_ack_with_data_noflags(buf,dlen); // send data
  313. }
  314. static void fill_buf_p(byte *buf,uint16_t len, const prog_char *progmem_s) {
  315. while (len--)
  316. *buf++ = pgm_read_byte(progmem_s++);
  317. }
  318. void client_icmp_request(byte *buf,byte *destip) {
  319. byte i=0;
  320. while(i<6){
  321. buf[ETH_DST_MAC +i]=gwmacaddr[i]; // gw mac in local lan or host mac
  322. buf[ETH_SRC_MAC +i]=macaddr[i];
  323. i++;
  324. }
  325. buf[ETH_TYPE_H_P] = ETHTYPE_IP_H_V;
  326. buf[ETH_TYPE_L_P] = ETHTYPE_IP_L_V;
  327. fill_buf_p(&buf[IP_P],9,iphdr);
  328. buf[IP_TOTLEN_L_P]=0x54;
  329. buf[IP_PROTO_P]=IP_PROTO_ICMP_V;
  330. i=0;
  331. while(i<4){
  332. buf[IP_DST_P+i]=destip[i];
  333. buf[IP_SRC_P+i]=ipaddr[i];
  334. i++;
  335. }
  336. fill_ip_hdr_checksum(buf);
  337. buf[ICMP_TYPE_P]=ICMP_TYPE_ECHOREQUEST_V;
  338. buf[ICMP_TYPE_P+1]=0; // code
  339. buf[ICMP_CHECKSUM_H_P]=0;
  340. buf[ICMP_CHECKSUM_L_P]=0;
  341. buf[ICMP_IDENT_H_P]=5; // some number
  342. buf[ICMP_IDENT_L_P]=ipaddr[3]; // last byte of my IP
  343. buf[ICMP_IDENT_L_P+1]=0; // seq number, high byte
  344. buf[ICMP_IDENT_L_P+2]=1; // seq number, low byte, we send only 1 ping at a time
  345. i=0;
  346. while(i<56){
  347. buf[ICMP_DATA_P+i]=PINGPATTERN;
  348. i++;
  349. }
  350. uint16_t ck=checksum(&buf[ICMP_TYPE_P], 56+8,0);
  351. buf[ICMP_CHECKSUM_H_P]=ck>>8;
  352. buf[ICMP_CHECKSUM_L_P]=ck;
  353. enc28j60PacketSend(98,buf);
  354. }
  355. void client_ntp_request(byte *buf,byte *ntpip,byte srcport) {
  356. byte i=0;
  357. while(i<6){
  358. buf[ETH_DST_MAC +i]=gwmacaddr[i]; // gw mac in local lan or host mac
  359. buf[ETH_SRC_MAC +i]=macaddr[i];
  360. i++;
  361. }
  362. buf[ETH_TYPE_H_P] = ETHTYPE_IP_H_V;
  363. buf[ETH_TYPE_L_P] = ETHTYPE_IP_L_V;
  364. fill_buf_p(&buf[IP_P],9,iphdr);
  365. buf[IP_TOTLEN_L_P]=0x4c;
  366. buf[IP_PROTO_P]=IP_PROTO_UDP_V;
  367. i=0;
  368. while(i<4){
  369. buf[IP_DST_P+i]=ntpip[i];
  370. buf[IP_SRC_P+i]=ipaddr[i];
  371. i++;
  372. }
  373. fill_ip_hdr_checksum(buf);
  374. buf[UDP_DST_PORT_H_P]=0;
  375. buf[UDP_DST_PORT_L_P]=0x7b; // ntp=123
  376. buf[UDP_SRC_PORT_H_P]=10;
  377. buf[UDP_SRC_PORT_L_P]=srcport; // lower 8 bit of src port
  378. buf[UDP_LEN_H_P]=0;
  379. buf[UDP_LEN_L_P]=56; // fixed len
  380. buf[UDP_CHECKSUM_H_P]=0;
  381. buf[UDP_CHECKSUM_L_P]=0;
  382. i=0;
  383. while(i<48){
  384. buf[UDP_DATA_P+i]=0;
  385. i++;
  386. }
  387. fill_buf_p(&buf[UDP_DATA_P],10,ntpreqhdr);
  388. uint16_t ck=checksum(&buf[IP_SRC_P], 16 + 48,1);
  389. buf[UDP_CHECKSUM_H_P]=ck>>8;
  390. buf[UDP_CHECKSUM_L_P]=ck;
  391. enc28j60PacketSend(90,buf);
  392. }
  393. byte client_ntp_process_answer(byte *buf,uint32_t *time,byte dstport_l){
  394. if (dstport_l && buf[UDP_DST_PORT_L_P]!=dstport_l)
  395. return 0;
  396. if (buf[UDP_LEN_H_P]!=0 || buf[UDP_LEN_L_P]!=56 || buf[UDP_SRC_PORT_L_P]!=0x7b)
  397. return 0;
  398. *time=((uint32_t)buf[0x52]<<24)|((uint32_t)buf[0x53]<<16)|((uint32_t)buf[0x54]<<8)|((uint32_t)buf[0x55]);
  399. return 1;
  400. }
  401. void send_udp_prepare(byte *buf,uint16_t sport, byte *dip, uint16_t dport) {
  402. byte i=0;
  403. while(i<6){
  404. buf[ETH_DST_MAC +i]=gwmacaddr[i]; // gw mac in local lan or host mac
  405. buf[ETH_SRC_MAC +i]=macaddr[i];
  406. i++;
  407. }
  408. buf[ETH_TYPE_H_P] = ETHTYPE_IP_H_V;
  409. buf[ETH_TYPE_L_P] = ETHTYPE_IP_L_V;
  410. fill_buf_p(&buf[IP_P],9,iphdr);
  411. buf[IP_TOTLEN_H_P]=0;
  412. buf[IP_PROTO_P]=IP_PROTO_UDP_V;
  413. i=0;
  414. while(i<4){
  415. buf[IP_DST_P+i]=dip[i];
  416. buf[IP_SRC_P+i]=ipaddr[i];
  417. i++;
  418. }
  419. buf[UDP_DST_PORT_H_P]=(dport>>8);
  420. buf[UDP_DST_PORT_L_P]=0xff&dport;
  421. buf[UDP_SRC_PORT_H_P]=(sport>>8);
  422. buf[UDP_SRC_PORT_L_P]=sport;
  423. buf[UDP_LEN_H_P]=0;
  424. buf[UDP_CHECKSUM_H_P]=0;
  425. buf[UDP_CHECKSUM_L_P]=0;
  426. }
  427. void send_udp_transmit(byte *buf,byte datalen) {
  428. buf[IP_TOTLEN_L_P]=IP_HEADER_LEN+UDP_HEADER_LEN+datalen;
  429. fill_ip_hdr_checksum(buf);
  430. buf[UDP_LEN_L_P]=UDP_HEADER_LEN+datalen;
  431. uint16_t ck=checksum(&buf[IP_SRC_P], 16 + datalen,1);
  432. buf[UDP_CHECKSUM_H_P]=ck>>8;
  433. buf[UDP_CHECKSUM_L_P]=ck;
  434. enc28j60PacketSend(UDP_HEADER_LEN+IP_HEADER_LEN+ETH_HEADER_LEN+datalen,buf);
  435. }
  436. void send_udp(byte *buf,char *data,byte datalen,uint16_t sport, byte *dip, uint16_t dport) {
  437. send_udp_prepare(buf,sport, dip, dport);
  438. byte i=0;
  439. if (datalen>220)
  440. datalen=220;
  441. i=0;
  442. while(i<datalen){
  443. buf[UDP_DATA_P+i]=data[i];
  444. i++;
  445. }
  446. send_udp_transmit(buf,datalen);
  447. }
  448. void send_wol(byte *buf,byte *wolmac) {
  449. byte i=0;
  450. byte m=0;
  451. byte pos=0;
  452. while(i<6){
  453. buf[ETH_DST_MAC +i]=0xff;
  454. buf[ETH_SRC_MAC +i]=macaddr[i];
  455. i++;
  456. }
  457. buf[ETH_TYPE_H_P] = ETHTYPE_IP_H_V;
  458. buf[ETH_TYPE_L_P] = ETHTYPE_IP_L_V;
  459. fill_buf_p(&buf[IP_P],9,iphdr);
  460. buf[IP_TOTLEN_L_P]=0x54;
  461. buf[IP_PROTO_P]=IP_PROTO_ICMP_V;
  462. i=0;
  463. while(i<4){
  464. buf[IP_SRC_P+i]=ipaddr[i];
  465. buf[IP_DST_P+i]=0xff;
  466. i++;
  467. }
  468. fill_ip_hdr_checksum(buf);
  469. buf[UDP_DST_PORT_H_P]=0;
  470. buf[UDP_DST_PORT_L_P]=0x9; // wol=normally 9
  471. buf[UDP_SRC_PORT_H_P]=10;
  472. buf[UDP_SRC_PORT_L_P]=0x42; // source port does not matter
  473. buf[UDP_LEN_H_P]=0;
  474. buf[UDP_LEN_L_P]=110; // fixed len
  475. buf[UDP_CHECKSUM_H_P]=0;
  476. buf[UDP_CHECKSUM_L_P]=0;
  477. i=0;
  478. while(i<6){
  479. buf[UDP_DATA_P+i]=0xff;
  480. i++;
  481. }
  482. m=0;
  483. pos=UDP_DATA_P+i;
  484. while (m<16){
  485. i=0;
  486. while(i<6){
  487. buf[pos]=wolmac[i];
  488. i++;
  489. pos++;
  490. }
  491. m++;
  492. }
  493. uint16_t ck=checksum(&buf[IP_SRC_P], 16+ 102,1);
  494. buf[UDP_CHECKSUM_H_P]=ck>>8;
  495. buf[UDP_CHECKSUM_L_P]=ck;
  496. enc28j60PacketSend(pos,buf);
  497. }
  498. // make a arp request
  499. void client_arp_whohas(byte *buf,byte *ip_we_search) {
  500. byte i=0;
  501. while(i<6){
  502. buf[ETH_DST_MAC +i]=0xff;
  503. buf[ETH_SRC_MAC +i]=macaddr[i];
  504. i++;
  505. }
  506. buf[ETH_TYPE_H_P] = ETHTYPE_ARP_H_V;
  507. buf[ETH_TYPE_L_P] = ETHTYPE_ARP_L_V;
  508. fill_buf_p(&buf[ETH_ARP_P],8,arpreqhdr);
  509. i=0;
  510. while(i<6){
  511. buf[ETH_ARP_SRC_MAC_P +i]=macaddr[i];
  512. buf[ETH_ARP_DST_MAC_P+i]=0;
  513. i++;
  514. }
  515. i=0;
  516. while(i<4){
  517. buf[ETH_ARP_DST_IP_P+i]=*(ip_we_search +i);
  518. buf[ETH_ARP_SRC_IP_P+i]=ipaddr[i];
  519. i++;
  520. }
  521. waitgwmac|=WGW_ACCEPT_ARP_REPLY;
  522. enc28j60PacketSend(0x2a,buf);
  523. }
  524. byte client_waiting_gw(void) {
  525. if (waitgwmac & WGW_HAVE_GW_MAC)
  526. return 0;
  527. return 1;
  528. }
  529. static byte client_store_gw_mac(byte *buf) {
  530. byte i=0;
  531. while(i<4){
  532. if (buf[ETH_ARP_SRC_IP_P+i]!=gwip[i])
  533. return 0;
  534. i++;
  535. }
  536. i=0;
  537. while(i<6){
  538. gwmacaddr[i]=buf[ETH_ARP_SRC_MAC_P +i];
  539. i++;
  540. }
  541. return 1;
  542. }
  543. static void client_gw_arp_refresh(void) {
  544. if (waitgwmac & WGW_HAVE_GW_MAC)
  545. waitgwmac|=WGW_REFRESHING;
  546. }
  547. void client_set_gwip(byte *gwipaddr) {
  548. byte i=0;
  549. waitgwmac=WGW_INITIAL_ARP; // causes an arp request in the packet loop
  550. while(i<4){
  551. gwip[i]=gwipaddr[i];
  552. i++;
  553. }
  554. }
  555. void client_tcp_set_serverip(byte *ipaddr) {
  556. byte i=0;
  557. while(i<4){
  558. tcpsrvip[i]=ipaddr[i];
  559. i++;
  560. }
  561. }
  562. static void client_syn(byte *buf,byte srcport,byte dstport_h,byte dstport_l) {
  563. byte i=0;
  564. while(i<6){
  565. buf[ETH_DST_MAC +i]=gwmacaddr[i]; // gw mac in local lan or host mac
  566. buf[ETH_SRC_MAC +i]=macaddr[i];
  567. i++;
  568. }
  569. buf[ETH_TYPE_H_P] = ETHTYPE_IP_H_V;
  570. buf[ETH_TYPE_L_P] = ETHTYPE_IP_L_V;
  571. fill_buf_p(&buf[IP_P],9,iphdr);
  572. buf[IP_TOTLEN_L_P]=44; // good for syn
  573. buf[IP_PROTO_P]=IP_PROTO_TCP_V;
  574. i=0;
  575. while(i<4){
  576. buf[IP_DST_P+i]=tcpsrvip[i];
  577. buf[IP_SRC_P+i]=ipaddr[i];
  578. i++;
  579. }
  580. fill_ip_hdr_checksum(buf);
  581. buf[TCP_DST_PORT_H_P]=dstport_h;
  582. buf[TCP_DST_PORT_L_P]=dstport_l;
  583. buf[TCP_SRC_PORT_H_P]=TCPCLIENT_SRC_PORT_H;
  584. buf[TCP_SRC_PORT_L_P]=srcport; // lower 8 bit of src port
  585. i=0;
  586. while(i<8){
  587. buf[TCP_SEQ_H_P+i]=0;
  588. i++;
  589. }
  590. buf[TCP_SEQ_H_P+2]= seqnum;
  591. seqnum+=3;
  592. buf[TCP_HEADER_LEN_P]=0x60; // 0x60=24 len: (0x60>>4) * 4
  593. buf[TCP_FLAGS_P]=TCP_FLAGS_SYN_V;
  594. buf[TCP_WIN_SIZE]=0x3; // 1024=0x400 768=0x300, initial window
  595. buf[TCP_WIN_SIZE+1]=0x0;
  596. buf[TCP_CHECKSUM_H_P]=0;
  597. buf[TCP_CHECKSUM_L_P]=0;
  598. buf[TCP_CHECKSUM_L_P+1]=0;
  599. buf[TCP_CHECKSUM_L_P+2]=0;
  600. buf[TCP_OPTIONS_P]=2;
  601. buf[TCP_OPTIONS_P+1]=4;
  602. buf[TCP_OPTIONS_P+2]=(CLIENTMSS>>8);
  603. buf[TCP_OPTIONS_P+3]=CLIENTMSS;
  604. uint16_t ck=checksum(&buf[IP_SRC_P], 8 +TCP_HEADER_LEN_PLAIN+4,2);
  605. buf[TCP_CHECKSUM_H_P]=ck>>8;
  606. buf[TCP_CHECKSUM_L_P]=ck;
  607. // 4 is the tcp mss option:
  608. enc28j60PacketSend(IP_HEADER_LEN+TCP_HEADER_LEN_PLAIN+ETH_HEADER_LEN+4,buf);
  609. }
  610. byte client_tcp_req(byte (*result_callback)(byte fd,byte statuscode,uint16_t data_start_pos_in_buf, uint16_t len_of_data),uint16_t (*datafill_callback)(byte fd),uint16_t port) {
  611. client_tcp_result_callback=result_callback;
  612. client_tcp_datafill_callback=datafill_callback;
  613. tcp_client_port_h=port>>8;
  614. tcp_client_port_l=port;
  615. tcp_client_state=1; // send a syn
  616. tcp_fd = (tcp_fd + 1) & 7;
  617. return tcp_fd;
  618. }
  619. static uint16_t www_client_internal_datafill_callback(byte fd){
  620. char strbuf[5];
  621. uint16_t len=0;
  622. if (fd==www_fd){
  623. if (browsertype==0){
  624. len=fill_tcp_data_p(bufptr,0,PSTR("GET "));
  625. len=fill_tcp_data_p(bufptr,len,client_urlbuf);
  626. len=fill_tcp_data(bufptr,len,client_urlbuf_var);
  627. len=fill_tcp_data_p(bufptr,len,PSTR(" HTTP/1.1\r\nHost: "));
  628. len=fill_tcp_data_p(bufptr,len,client_hoststr);
  629. len=fill_tcp_data_p(bufptr,len,PSTR("\r\nUser-Agent: tgr/1.0\r\nAccept: text/html\r\nConnection: close\r\n\r\n"));
  630. }else{
  631. len=fill_tcp_data_p(bufptr,0,PSTR("POST "));
  632. len=fill_tcp_data_p(bufptr,len,client_urlbuf);
  633. len=fill_tcp_data_p(bufptr,len,PSTR(" HTTP/1.1\r\nHost: "));
  634. len=fill_tcp_data_p(bufptr,len,client_hoststr);
  635. if (client_additionalheaderline){
  636. len=fill_tcp_data_p(bufptr,len,PSTR("\r\n"));
  637. len=fill_tcp_data_p(bufptr,len,client_additionalheaderline);
  638. }
  639. len=fill_tcp_data_p(bufptr,len,PSTR("\r\nUser-Agent: tgr/1.1\r\nAccept: */*\r\nConnection: close\r\n"));
  640. len=fill_tcp_data_p(bufptr,len,PSTR("Content-Length: "));
  641. itoa(strlen(client_postval),strbuf,10);
  642. len=fill_tcp_data(bufptr,len,strbuf);
  643. len=fill_tcp_data_p(bufptr,len,PSTR("\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n"));
  644. len=fill_tcp_data(bufptr,len,client_postval);
  645. }
  646. }
  647. return len;
  648. }
  649. static byte www_client_internal_result_callback(byte fd, byte statuscode, uint16_t datapos, uint16_t len_of_data){
  650. if (fd!=www_fd)
  651. (*client_browser_callback)(4,0,0);
  652. else if (statuscode==0 && len_of_data>12 && client_browser_callback){
  653. byte f = strncmp("200",(char *)&(bufptr[datapos+9]),3) != 0;
  654. (*client_browser_callback)(f, ((uint16_t)TCP_SRC_PORT_H_P+(bufptr[TCP_HEADER_LEN_P]>>4)*4),len_of_data);
  655. }
  656. return 0;
  657. }
  658. void client_browse_url(prog_char *urlbuf, char *urlbuf_varpart, prog_char *hoststr,void (*callback)(byte,uint16_t,uint16_t)) {
  659. client_urlbuf=urlbuf;
  660. client_urlbuf_var=urlbuf_varpart;
  661. client_hoststr=hoststr;
  662. browsertype=0;
  663. client_browser_callback=callback;
  664. www_fd=client_tcp_req(&www_client_internal_result_callback,&www_client_internal_datafill_callback,80);
  665. }
  666. void client_http_post(prog_char *urlbuf, prog_char *hoststr, prog_char *additionalheaderline,char *postval,void (*callback)(byte,uint16_t,uint16_t)) {
  667. client_urlbuf=urlbuf;
  668. client_hoststr=hoststr;
  669. client_additionalheaderline=additionalheaderline;
  670. client_postval=postval;
  671. browsertype=1;
  672. client_browser_callback=callback;
  673. www_fd=client_tcp_req(&www_client_internal_result_callback,&www_client_internal_datafill_callback,80);
  674. }
  675. void register_ping_rec_callback(void (*callback)(byte *srcip)) {
  676. icmp_callback=callback;
  677. }
  678. byte packetloop_icmp_checkreply(byte *buf,byte *ip_monitoredhost) {
  679. return buf[IP_PROTO_P]==IP_PROTO_ICMP_V &&
  680. buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREPLY_V &&
  681. buf[ICMP_DATA_P]== PINGPATTERN &&
  682. check_ip_message_is_from(buf,ip_monitoredhost);
  683. }
  684. uint16_t packetloop_icmp_tcp(byte *buf,uint16_t plen) {
  685. uint16_t len;
  686. byte send_fin=0;
  687. uint16_t tcpstart;
  688. uint16_t save_len;
  689. if (plen==0){
  690. if ((waitgwmac & WGW_INITIAL_ARP||waitgwmac & WGW_REFRESHING) && delaycnt==0&& enc28j60linkup())
  691. client_arp_whohas(buf,gwip);
  692. delaycnt++;
  693. if (tcp_client_state==1 && (waitgwmac & WGW_HAVE_GW_MAC)){ // send a syn
  694. tcp_client_state=2;
  695. tcpclient_src_port_l++; // allocate a new port
  696. client_syn(buf,((tcp_fd<<5) | (0x1f & tcpclient_src_port_l)),tcp_client_port_h,tcp_client_port_l);
  697. }
  698. return 0;
  699. }
  700. if (eth_type_is_arp_and_my_ip(buf,plen)){
  701. if (buf[ETH_ARP_OPCODE_L_P]==ETH_ARP_OPCODE_REQ_L_V)
  702. make_arp_answer_from_request(buf);
  703. if (waitgwmac & WGW_ACCEPT_ARP_REPLY && (buf[ETH_ARP_OPCODE_L_P]==ETH_ARP_OPCODE_REPLY_L_V) && client_store_gw_mac(buf))
  704. waitgwmac=WGW_HAVE_GW_MAC;
  705. return 0;
  706. }
  707. if (eth_type_is_ip_and_my_ip(buf,plen)==0)
  708. return 0;
  709. if (buf[IP_PROTO_P]==IP_PROTO_ICMP_V && buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V){
  710. if (icmp_callback)
  711. (*icmp_callback)(&(buf[IP_SRC_P]));
  712. make_echo_reply_from_request(buf,plen);
  713. return 0;
  714. }
  715. if (plen<54 && buf[IP_PROTO_P]!=IP_PROTO_TCP_V )
  716. return 0;
  717. if ( buf[TCP_DST_PORT_H_P]==TCPCLIENT_SRC_PORT_H){
  718. bufptr=buf;
  719. if (check_ip_message_is_from(buf,tcpsrvip)==0)
  720. return 0;
  721. if (buf[TCP_FLAGS_P] & TCP_FLAGS_RST_V){
  722. if (client_tcp_result_callback)
  723. (*client_tcp_result_callback)((buf[TCP_DST_PORT_L_P]>>5)&0x7,3,0,0);
  724. tcp_client_state=5;
  725. return 0;
  726. }
  727. len=get_tcp_data_len(buf);
  728. if (tcp_client_state==2){
  729. if ((buf[TCP_FLAGS_P] & TCP_FLAGS_SYN_V) && (buf[TCP_FLAGS_P] &TCP_FLAGS_ACK_V)){
  730. make_tcp_ack_from_any(buf,0,0);
  731. buf[TCP_FLAGS_P]=TCP_FLAGS_ACK_V|TCP_FLAGS_PUSH_V;
  732. if (client_tcp_datafill_callback)
  733. len=(*client_tcp_datafill_callback)((buf[TCP_SRC_PORT_L_P]>>5)&0x7);
  734. else
  735. len=0;
  736. tcp_client_state=3;
  737. make_tcp_ack_with_data_noflags(buf,len);
  738. return 0;
  739. }else{
  740. tcp_client_state=1; // retry
  741. len++;
  742. if (buf[TCP_FLAGS_P] & TCP_FLAGS_ACK_V)
  743. len=0;
  744. make_tcp_ack_from_any(buf,len,TCP_FLAGS_RST_V);
  745. return 0;
  746. }
  747. }
  748. if (tcp_client_state==3 && len>0){
  749. tcp_client_state=4;
  750. if (client_tcp_result_callback){
  751. tcpstart=TCP_DATA_START; // TCP_DATA_START is a formula
  752. if (tcpstart>plen-8)
  753. tcpstart=plen-8; // dummy but save
  754. save_len=len;
  755. if (tcpstart+len>plen)
  756. save_len=plen-tcpstart;
  757. send_fin = (*client_tcp_result_callback)((buf[TCP_DST_PORT_L_P]>>5)&0x7,0,tcpstart,save_len);
  758. }
  759. if (send_fin){
  760. make_tcp_ack_from_any(buf,len,TCP_FLAGS_PUSH_V|TCP_FLAGS_FIN_V);
  761. tcp_client_state=5;
  762. return 0;
  763. }
  764. }
  765. if (tcp_client_state==5)
  766. return 0;
  767. if (buf[TCP_FLAGS_P] & TCP_FLAGS_FIN_V){
  768. make_tcp_ack_from_any(buf,len+1,TCP_FLAGS_PUSH_V|TCP_FLAGS_FIN_V);
  769. tcp_client_state=5; // connection terminated
  770. return 0;
  771. }
  772. if (len>0)
  773. make_tcp_ack_from_any(buf,len,0);
  774. return 0;
  775. }
  776. if (buf[TCP_DST_PORT_H_P]==wwwport_h && buf[TCP_DST_PORT_L_P]==wwwport_l){
  777. if (buf[TCP_FLAGS_P] & TCP_FLAGS_SYN_V){
  778. make_tcp_synack_from_syn(buf);
  779. return 0;
  780. }
  781. if (buf[TCP_FLAGS_P] & TCP_FLAGS_ACK_V){
  782. info_data_len=get_tcp_data_len(buf);
  783. if (info_data_len==0){
  784. if (buf[TCP_FLAGS_P] & TCP_FLAGS_FIN_V)
  785. make_tcp_ack_from_any(buf,0,0);
  786. return 0;
  787. }
  788. len=TCP_DATA_START; // TCP_DATA_START is a formula
  789. if (len>plen-8)
  790. return 0;
  791. return len;
  792. }
  793. }
  794. return 0;
  795. }