mirror of
https://github.com/isometimes/rpi4-osdev
synced 2024-11-25 03:30:39 +00:00
212 lines
10 KiB
C
212 lines
10 KiB
C
/*********************************************
|
|
* vim:sw=8:ts=8:si:et
|
|
* To use the above modeline in vim you must have "set modeline" in your .vimrc
|
|
* Author: Guido Socher
|
|
* Copyright:LGPL V2
|
|
* See http://www.gnu.org/licenses/old-licenses/lgpl-2.0.html
|
|
*
|
|
* IP/ARP/UDP/TCP functions
|
|
*
|
|
* Chip type : ATMEGA88/168/328/644 with ENC28J60
|
|
*********************************************/
|
|
//@{
|
|
#ifndef IP_ARP_UDP_TCP_H
|
|
#define IP_ARP_UDP_TCP_H 1
|
|
|
|
#include "net.h"
|
|
#include "../net/enc28j60.h"
|
|
#include "../kernel/kernel.h"
|
|
#include "../include/fb.h"
|
|
#include "ip_config.h"
|
|
|
|
// set my own mac address:
|
|
extern void init_mac(uint8_t *mymac); // not needed if you call init_udp_or_www_server
|
|
// -- web server functions --
|
|
#if defined (WWW_server) || defined (UDP_server)
|
|
// you must call this function once before you use any of the other server functions:
|
|
// mymac may be set to NULL in this function if init_mac was used before
|
|
// init_ip_arp_udp_tcp is now replaced by init_udp_or_www_server and the www_server_port function.
|
|
extern void init_udp_or_www_server(uint8_t *mymac,uint8_t *myip);
|
|
#endif
|
|
|
|
#if defined (WWW_server)
|
|
extern void www_server_port(uint16_t port); // not needed if you want port 80
|
|
// send data from the web server to the client:
|
|
extern void www_server_reply(uint8_t *buf,uint16_t dlen);
|
|
#endif
|
|
|
|
// for a UDP server:
|
|
#if defined (UDP_server)
|
|
extern uint8_t eth_type_is_ip_and_my_ip(uint8_t *buf,uint16_t len);
|
|
extern void make_udp_reply_from_request_udpdat_ready(uint8_t *buf,uint16_t datalen,uint16_t port);
|
|
extern void make_udp_reply_from_request(uint8_t *buf,char *data,uint8_t datalen,uint16_t port);
|
|
#endif
|
|
// return 0 to just continue in the packet loop and return the position
|
|
// of the tcp data if there is tcp data part:
|
|
extern uint16_t packetloop_arp_icmp_tcp(uint8_t *buf,uint16_t plen);
|
|
// functions to fill the web pages with data:
|
|
extern uint16_t fill_tcp_data_p(uint8_t *buf,uint16_t pos, const uint8_t *progmem_s);
|
|
extern uint16_t fill_tcp_data_string(uint8_t *buf,uint16_t pos, char *reply);
|
|
|
|
extern uint16_t fill_tcp_data(uint8_t *buf,uint16_t pos, const char *s);
|
|
// fill a binary string of len data into the tcp packet:
|
|
extern uint16_t fill_tcp_data_len(uint8_t *buf,uint16_t pos, const uint8_t *s, uint8_t len);
|
|
|
|
// -- client only functions --
|
|
#if defined (WWW_client) || defined (NTP_client) || defined (UDP_client) || defined (TCP_client) || defined (PING_client)
|
|
extern void client_ifconfig(uint8_t *ip,uint8_t *netmask);
|
|
// route_via_gw can be used decide if a packed needs to be routed via GW or can be found on the LAN:
|
|
extern uint8_t route_via_gw(uint8_t *destip); // returns 1 if destip must be routed via the GW. Returns 0 if destip is on the local LAN
|
|
//
|
|
// The get_mac_with_arp function can be used to find the MAC address of
|
|
// a host that is directly connected to the same LAN. It translates the IP address into
|
|
// a MAC address.
|
|
// You need to provide a callback function. That function will be executed once the
|
|
// MAC address is found. We do this to not block execution in the main loop.
|
|
// NOTE: you can only do one MAC address resolution at a time. The reference_number is just
|
|
// a number given back to you to make it easier to know what this relates to.
|
|
//
|
|
// You declare the callback function:
|
|
//
|
|
//#define TRANS_NUM_GWMAC 12
|
|
//void arpresolver_result_callback(uint8_t *ip __attribute__((unused)),uint8_t reference_number,uint8_t *mac){ // the __attribute__((unused)) is a gcc compiler directive to avoid warnings about unsed variables.
|
|
// uint8_t i=0;
|
|
// if (reference_number==TRANS_NUM_GWMAC){
|
|
// // copy mac address over:
|
|
// while(i<6){gwmac[i]=mac[i];i++;}
|
|
// }
|
|
//}
|
|
//
|
|
// and then you can just call get_mac_with_arp like this:
|
|
// get_mac_with_arp(gwip,TRANS_NUM_GWMAC,&arpresolver_result_callback);
|
|
// Note: you must have initialized the stack with init_udp_or_www_server or client_ifconfig
|
|
// before you can use get_mac_with_arp(). The arp request will automatically be repeated if
|
|
// there is no answer.
|
|
extern void get_mac_with_arp(uint8_t *ip, uint8_t reference_number,void (*arp_result_callback)(uint8_t *ip,uint8_t reference_number,uint8_t *mac));
|
|
uint8_t get_mac_with_arp_wait(void); // checks current ongoing transaction, retuns 0 when the transaction is over
|
|
#endif
|
|
|
|
#ifdef TCP_client
|
|
// To use the tcp client you need to:
|
|
//
|
|
// Declare a callback function to get the result (tcp data from the server):
|
|
//
|
|
// uint8_t your_client_tcp_result_callback(uint8_t fd, uint8_t statuscode,uint16_t data_start_pos_in_buf, uint16_t len_of_data){
|
|
// ...your code;
|
|
// return(close_tcp_session);
|
|
// }
|
|
//
|
|
// statuscode=0 means the buffer has valid data, otherwise len and pos_in_buf
|
|
// are invalid. That is: do to use data_start_pos_in_buf and len_of_data
|
|
// if statuscode!=0.
|
|
//
|
|
// This callback gives you access to the TCP data of the first
|
|
// packet returned from the server. You should aim to minimize the server
|
|
// output such that this will be the only packet.
|
|
//
|
|
// close_tcp_session=1 means close the session now. close_tcp_session=0
|
|
// read all data and leave it to the other side to close it.
|
|
// If you connect to a web server then you want close_tcp_session=0.
|
|
// If you connect to a modbus/tcp equipment then you want close_tcp_session=1
|
|
//
|
|
// Declare a callback function to be called in order to fill in the
|
|
//
|
|
// request (tcp data sent to the server):
|
|
// uint16_t your_client_tcp_datafill_callback(uint8_t fd){...your code;return(len_of_data_filled_in);}
|
|
//
|
|
// Now call:
|
|
// fd=client_tcp_req(&your_client_tcp_result_callback,&your_client_tcp_datafill_callback,portnumber);
|
|
//
|
|
// fd is a file descriptor like number that you get back in the fill and result
|
|
// function so you know to which call of client_tcp_req this callback belongs.
|
|
//
|
|
// You can not start different clients (e.g modbus and web) at the
|
|
// same time but you can start them one after each other. That is
|
|
// when the request has timed out or when the result_callback was
|
|
// executed then you can start a new one. The fd makes it still possible to
|
|
// distinguish in the callback code the different types you started.
|
|
//
|
|
// Note that you might never get called back if the other side does
|
|
// not answer. A timer would be needed to recongnize such a condition.
|
|
//
|
|
// We use callback functions because that is the best implementation
|
|
// given the fact that we have very little RAM memory.
|
|
//
|
|
extern uint8_t client_tcp_req(uint8_t (*result_callback)(uint8_t fd,uint8_t statuscode,uint16_t data_start_pos_in_buf, uint16_t len_of_data),uint16_t (*datafill_callback)(uint8_t fd),uint16_t port,uint8_t *dstip,uint8_t *dstmac);
|
|
#endif
|
|
|
|
#ifdef WWW_client
|
|
// ----- http get
|
|
// The string buffers to which urlbuf_varpart and hoststr are pointing
|
|
// must not be changed until the callback is executed.
|
|
extern void client_browse_url(const prog_char *urlbuf, char *urlbuf_varpart, const char *hoststr,void (*callback)(uint16_t,uint16_t,uint16_t),uint8_t *dstip,uint8_t *dstmac);
|
|
// The callback is a reference to a function which must look like this:
|
|
// void browserresult_callback(uint16_t webstatuscode,uint16_t datapos,uint16_t len)
|
|
// webstatuscode is zero if there was no proper reply from the server (garbage message total communication failure, this is rare).
|
|
// webstatuscode is otherwise the http status code (e.g webstatuscode=200 for 200 OK);
|
|
// For possible status codes look at http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
|
// Basically 2xx is success and any 5xx, 4xx is a failure.
|
|
// ----- http post
|
|
// client web browser using http POST operation:
|
|
// additionalheaderline must be set to NULL if not used.
|
|
// The string buffers to which urlbuf_varpart and hoststr are pointing
|
|
// must not be changed until the callback is executed.
|
|
// postval is a string buffer which can only be de-allocated by the caller
|
|
// when the post operation was really done (e.g when callback was executed).
|
|
// postval must be urlencoded.
|
|
extern void client_http_post(const prog_char *urlbuf, char *urlbuf_varpart,const char *hoststr, const prog_char *additionalheaderline,char *postval,void (*callback)(uint16_t,uint16_t,uint16_t),uint8_t *dstip,uint8_t *dstmac);
|
|
// The callback is a reference to a function which must look like this:
|
|
// void browserresult_callback(uint16_t webstatuscode,uint16_t datapos,uint16_t len)
|
|
// webstatuscode is zero if there was no proper reply from the server (garbage message total communication failure, this is rare).
|
|
// webstatuscode is otherwise the http status code (e.g webstatuscode=200 for 200 OK);
|
|
#endif
|
|
|
|
#ifdef NTP_client
|
|
// be careful to not mix client_ntp_request with situations where you are filling
|
|
// a web-page. Normally you will be using the same packet buffer and
|
|
// client_ntp_request writes immediately to buf. You might need to
|
|
// set a marker and call client_ntp_request when your main loop is idle.
|
|
extern void client_ntp_request(uint8_t *buf,uint8_t *ntpip,uint8_t srcport,uint8_t *dstmac);
|
|
extern uint8_t client_ntp_process_answer(uint8_t *buf,uint32_t *time,uint8_t dstport_l);
|
|
#endif
|
|
|
|
#ifdef UDP_client
|
|
// There are two ways of using this UDP client:
|
|
//
|
|
// 1) you call send_udp_prepare, you fill the data yourself into buf starting at buf[UDP_DATA_P],
|
|
// you send the packet by calling send_udp_transmit
|
|
//
|
|
// 2) You just allocate a large enough buffer for you data and you call send_udp and nothing else
|
|
// needs to be done.
|
|
//
|
|
extern void send_udp_prepare(uint8_t *buf,uint16_t sport, const uint8_t *dip, uint16_t dport,const uint8_t *dstmac);
|
|
extern void send_udp_transmit(uint8_t *buf,uint16_t datalen);
|
|
|
|
// send_udp sends via gwip, you must call client_set_gwip at startup, datalen must be less than 220 bytes
|
|
extern void send_udp(uint8_t *buf,char *data,uint8_t datalen,uint16_t sport, const uint8_t *dip, uint16_t dport,const uint8_t *dstmac);
|
|
#endif
|
|
|
|
// you can find out who ping-ed you if you want:
|
|
extern void register_ping_rec_callback(void (*callback)(uint8_t *srcip));
|
|
|
|
#ifdef PING_client
|
|
extern void client_icmp_request(uint8_t *buf,uint8_t *destip,uint8_t *dstmac);
|
|
// you must loop over this function to check if there was a ping reply:
|
|
extern uint8_t packetloop_icmp_checkreply(uint8_t *buf,uint8_t *ip_monitoredhost);
|
|
#endif // PING_client
|
|
|
|
#ifdef WOL_client
|
|
extern void send_wol(uint8_t *buf,uint8_t *wolmac);
|
|
#endif // WOL_client
|
|
|
|
#if defined GRATARP
|
|
// send a Gratuitous arp, this is to refresh the arp
|
|
// cash of routers and switches. It can improve the response
|
|
// time in wifi networks as some wifi equipment expects the initial
|
|
// communication to not start from the network side. That is wrong
|
|
// but some consumer devices are made like this.
|
|
extern uint8_t gratutious_arp(uint8_t *buf);
|
|
#endif // GRATARP
|
|
|
|
#endif /* IP_ARP_UDP_TCP_H */
|
|
//@}
|