Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <Ethernet.h>
- #include <ASocket.h>
- #include <EEPROM.h>
- #include "Dhcp.h"
- #ifdef HOST_NAME
- #undef HOST_NAME
- #endif
- #define HOST_NAME "myarduino"
- #define DEBUG
- // where the MAC address starts in EEPROM.
- #define MACADDR_START 0
- #define BUFFER_LEN 64
- enum receive_frame_state { COMMAND_READ_WAIT, COMMAND_READ,
- HEADER_KEY_READ_WAIT, HEADER_KEY_READ,
- HEADER_VAL_READ_WAIT, HEADER_VAL_READ,
- BODY_READ_WAIT, BODY_READ,
- FRAME_DONE_CLEANUP, FRAME_DONE };
- enum Cmd { CONNECT, CONNECTED, RECEIPT, MESSAGE, ERROR, UNKNOWN = 900 };
- struct hash {
- char *key;
- char *value;
- };
- struct stomp_frame {
- Cmd cmd;
- char *header;
- struct hash **headers;
- char *content;
- };
- typedef struct stomp_frame STOMP_FRAME;
- /* */
- struct stomp_message {
- char *header;
- char *content;
- };
- /*
- typedef struct stomp_message STOMP_MESSAGE;
- */
- struct stomp_connection {
- unsigned short port;
- byte broker_ip[4]; // aaa.bbb.ccc.ddd
- char *username;
- char *password;
- char buffer[BUFFER_LEN];
- // Some socket here
- };
- typedef struct stomp_connection STOMP_CONNECTION;
- unsigned long time;
- STOMP_CONNECTION conn;
- byte *mac = (byte *)malloc(sizeof(byte) * 6);
- byte my_ip[] = { 192, 168, 2, 4 };
- ASocket as;
- #define SERVER_CONNECT 0
- #define SERVER_CONNECTING 1
- #define SERVER_RECEIVE 2
- #define NET_IDLE 3
- #define NET_TIMER 4
- uint8 networkState = SERVER_CONNECT;
- void stomp_login(ASocket *, struct stomp_connection *);
- uint8 read_char(ASocket *as);
- char * stpcpy(char *, const char *);
- void loop_forever(void);
- void setup() {
- Serial.begin(9600);
- read_mac_address();
- Ethernet.begin(mac, my_ip);
- conn.broker_ip[0] = 192;conn.broker_ip[1] = 168;
- conn.broker_ip[2] = 2 ;conn.broker_ip[3] = 1;
- conn.port = 61613;
- conn.username = "";
- conn.password = "";
- Serial.println("Done setup");
- }
- void loop() {
- switch(networkState) {
- case SERVER_CONNECT:
- Serial.println("Connecting...");
- if (as.initTCP(0)) {
- as.connectTCP(conn.broker_ip,conn.port);
- networkState = SERVER_CONNECTING;
- }
- else {
- Serial.println("Failed to init socket");
- networkState = NET_IDLE;
- }
- break;
- case SERVER_CONNECTING:
- if (as.isConnectedTCP()) {
- Serial.println("Connected. Trying to login to STOMP");
- stomp_login(&as,&conn);
- networkState = SERVER_RECEIVE;
- }
- break;
- case SERVER_RECEIVE:
- if (as.isConnectedTCP()) {
- // Serial.println("SERVER RECV - is connected");
- if (as.available()) {
- uint8 c;
- as.read(&c,1);
- Serial.print(c);
- }
- }
- else {
- as.disconnectTCP();
- as.close();
- networkState = NET_IDLE;
- }
- break;
- case NET_IDLE:
- networkState = NET_TIMER;
- break;
- }
- }
- //////////////////
- void stomp_login(ASocket *as, struct stomp_connection *conn) {
- STOMP_FRAME frame;
- char *p;
- frame.cmd = CONNECT;
- frame.content = (char *)malloc(1 * sizeof(char));
- strcpy(frame.content,"");
- frame.header = (char *)malloc( sizeof(char) * ( strlen(conn->username) +
- strlen(conn->password) +
- (2 * strlen("\n")) +
- strlen("login:") +
- strlen("passcode:") + 1
- )
- );
- p = stpcpy(frame.header,"login:");
- p = stpcpy(p,conn->username);
- p = stpcpy(p,"\n");
- p = stpcpy(p,"passcode:");
- p = stpcpy(p,conn->password);
- p = stpcpy(p,"\n");
- send_frame(as,&frame);
- receive_frame(as,&frame);
- Serial.print("First header: ");
- Serial.println(frame.headers[0]->key);
- Serial.print("First header value: ");
- Serial.println(frame.headers[0]->value);
- as->close();
- loop_forever();
- }
- void send_frame(ASocket *as, struct stomp_frame *frame) {
- time = micros();
- as->beginPacketTCP();
- switch (frame->cmd) {
- case CONNECT:
- as->write("CONNECT\n");
- break;
- }
- as->write(frame->header);
- as->write("\n"); // end of header
- as->write(frame->content);
- as->write((byte *) "\0",1); // end of content
- as->send();
- }
- /*
- * Read ONE frame from the STOMP connection by reading character by character
- until the entire frame has been read.
- 1. Until one of the conditions below is met after reading a character, if
- it fails to meet criteria for 2-6 add it to a buffer. Once the character
- being read meets the criteria read out of the buffer, assign
- appropriately, tack on the single-character buffer, and reset the buffer.
- 2. read characters one at a time until a newline is detected; this is the
- command. (read_command)
- 3. read characters one at a time until two newlines in a row are detected;
- this marks the end of headers. Headers are defined by a series of
- matches to /(\w+):(\w*)\n/
- 4. if one of the headers is 'content-length' read $2 number of characters
- following the second newline terminating header block; this is the
- content of the frame.
- 5. if the 'content-length' header is absent read until a NULL character
- following the second newline terminating header block; this is the
- content of the frame.
- 6. Stop reading after the content of the frame is assembled.
- */
- void receive_frame(ASocket *as,struct stomp_frame *frame) {
- char buffer[BUFFER_LEN];
- uint8 i = 0; /* Index to buffer */
- uint8 j = 0; /* Generic looping var */
- uint8 c; /* One character from the ASocket connection */
- int header_idx = -1;
- receive_frame_state framestate = COMMAND_READ_WAIT;
- signed int content_length = -1;
- uint8 l = 0; /* Bytes read of content_length */
- bool seen_content_length = false;
- frame->headers = NULL;
- while ( framestate != FRAME_DONE ) {
- // Serial.print("framestate = ");
- // Serial.println(framestate,DEC);
- switch(framestate) {
- // Set us up to read the command
- case COMMAND_READ_WAIT:
- framestate = COMMAND_READ;
- break; // COMMAND_READ_WAIT
- // Read the Command
- case COMMAND_READ:
- c = read_char(as);
- switch (c) {
- case 'C':
- frame->cmd = CONNECTED;
- j = 8; /* Read off 8 characters from the packet CONNECTED\0 - 1 */
- break;
- case 'R':
- frame->cmd = RECEIPT;
- j = 5;
- break;
- case 'M':
- frame->cmd = MESSAGE;
- j = 5;
- break;
- case 'E':
- frame->cmd = ERROR;
- j = 4;
- break;
- default:
- frame->cmd = UNKNOWN;
- j = 0;
- break;
- } /* end switch (c) */
- j += 1; /* ...and the newline too */
- while(j-- > 0)
- read_char(as);
- framestate = HEADER_KEY_READ_WAIT;
- break; // COMMAND_READ
- /* Set us up to read some headers */
- case HEADER_KEY_READ_WAIT:
- /* Initialize frame->headers with enough space for one header. */
- frame->headers = (struct hash **)realloc(frame->headers, ++header_idx *
- sizeof(struct hash *)
- );
- /* Here, we'll initialize these to NULL for our own sanity later on */
- frame->headers[header_idx]->key = NULL;
- frame->headers[header_idx]->value = NULL;
- framestate = HEADER_KEY_READ;
- break; // HEADER_KEY_READ_WAIT
- case HEADER_KEY_READ:
- c = read_char(as);
- switch(c) {
- case ':':
- /*
- Serial.print("HEADER_KEY_READ: encounted : with ");
- Serial.print(as->available(),DEC);
- Serial.print(" bytes to read");
- Serial.print(" i = ");
- Serial.print(i,DEC);
- Serial.print(" header_idx = ");
- Serial.println(header_idx,DEC);
- */
- // Encountered the :, we're done reading value
- frame->headers[header_idx]->key = (char *)malloc((1 + i) * sizeof(char));
- for(j = 0; j < i; j++) {
- /*
- Serial.print("HEADER_KEY_READ: in (before) loop ");
- Serial.print(as->available(),DEC);
- Serial.print(" bytes to read");
- Serial.print(" i = ");
- Serial.print(i,DEC);
- Serial.print(" j = ");
- Serial.print(j,DEC);
- Serial.print(" header_idx = ");
- Serial.println(header_idx,DEC);
- */
- frame->headers[header_idx]->key[j] = buffer[j];
- /*
- Serial.print("HEADER_KEY_READ: in (after) loop ");
- Serial.print(as->available(),DEC);
- Serial.print(" bytes to read");
- Serial.print(" i = ");
- Serial.print(i,DEC);
- Serial.print(" j = ");
- Serial.print(j,DEC);
- Serial.print(" header_idx = ");
- Serial.println(header_idx,DEC);
- */
- }
- frame->headers[header_idx]->key[i] = '\0';
- i = j = 0;
- framestate = HEADER_VAL_READ_WAIT;
- break; // :
- // when reading a \n here we're done reading headers.
- case '\n':
- if (i == 0)
- framestate = BODY_READ_WAIT;
- break; // \n
- default:
- if (i < BUFFER_LEN)
- buffer[i++] = c;
- else
- loop_forever();
- break; //default
- }
- break; // HEADER_KEY_READ
- case HEADER_VAL_READ_WAIT:
- framestate = HEADER_VAL_READ;
- break; // HEADER_VAL_READ_WAIT
- case HEADER_VAL_READ:
- c = read_char(as);
- // Serial.print("in HEADER_VAL_READ - read a character: ");
- // Serial.println(c);
- switch (c) {
- case '\n':
- frame->headers[header_idx]->value = (char *)malloc((1 + i) * sizeof(char));
- for(j = 0; j < i; j++)
- frame->headers[header_idx]->value[j] = buffer[j];
- frame->headers[header_idx]->value[i] = '\0';
- i = j = 0;
- framestate = HEADER_KEY_READ_WAIT;
- break; // \n
- default:
- if (i < BUFFER_LEN)
- buffer[i++] = c;
- else
- loop_forever();
- break; //default
- }
- //framestate = HEADER_KEY_READ_WAIT;
- break; // HEADER_VAL_READ
- case BODY_READ_WAIT:
- frame->content = NULL; // I'll handle the memory... (* gulp *)
- l = 0; /* read 0 bytes of body content */
- for(j = header_idx; j > 0; j--) {
- if ( (strcmp(frame->headers[j]->key,"content-length") == 0)) {
- content_length = atoi(frame->headers[j]->value);
- frame->content = (char *)malloc(content_length * sizeof(char));
- }
- }
- framestate = BODY_READ;
- break; // BODY_READ_WAIT
- case BODY_READ:
- c = read_char(as);
- l += 1;
- switch(c) {
- case '\0':
- // if content_length > 0 read that many bytes
- if (content_length > 0) {
- frame->content[l - 1] = c;
- content_length -= 1;
- /* UGLY - FIXME. I shouldn't need this otherwise I read a byte of the NEXT FRAME!! */
- if (content_length == 0)
- framestate = FRAME_DONE_CLEANUP;
- }
- /* End of the body/frame */
- else {
- for (j = 0; j < i; j++)
- frame->content[j] = buffer[i];
- frame->content[i + 1] = '\0';
- framestate = FRAME_DONE_CLEANUP;
- }
- break; // \0
- default:
- if (i < BUFFER_LEN - 1)
- buffer[i++] = c;
- else // FIXME: I should fix this and be smart about BUFFER_LEN and l
- loop_forever();
- break; // default
- } // switch(c)
- framestate = FRAME_DONE_CLEANUP;
- break; // BODY_READ
- case FRAME_DONE_CLEANUP:
- /* Check to see if the last-created header has value, else realloc -1
- if (frame->headers[header_idx]->key == NULL &&
- frame->headers[header_idx]->value == NULL) {
- frame->headers = (struct hash **)realloc(frame->headers, --header_idx *
- sizeof(struct hash *));
- } */
- framestate = FRAME_DONE;
- break; // FRAME_DONE_CLEANUP
- } /* end switch(framestate) */
- }
- }
- uint8 read_char(ASocket *as) {
- uint8 c;
- /*
- Serial.print("read_char(): isConnectedTCP = ");
- Serial.print(as->isConnectedTCP(),HEX);
- Serial.print(" available = ");
- Serial.print(as->available(),DEC);
- Serial.print(" Time = ");
- Serial.println(micros() - time);
- */
- while( ! as->isConnectedTCP() || as->available() <= 0) {
- /*
- Serial.print("read_char(): isConnectedTCP = ");
- Serial.print(as->isConnectedTCP(),HEX);
- Serial.print(" available = ");
- Serial.print(as->available(),DEC);
- Serial.print(" Time = ");
- Serial.println(micros() - time);
- */
- Serial.println("read_char: Waiting for data");
- delay(2000);
- }
- as->read(&c,1);
- // Serial.print("Read char: ");
- // Serial.println(c);
- return c;
- }
- void loop_forever(void) {
- for (;;) {
- delay(1000);
- Serial.println("loop_forever()");
- }
- }
- void read_mac_address() {
- for (int i = MACADDR_START; i < 6; i++) {
- *mac = EEPROM.read(i); // Assign value (pointed to by `mac`) to contents
- // of EEPROM.
- mac++; // Move to next memory space
- }
- mac -= 6; // Set pointer location back to the start of
- // the allocated memory space.
- }
- char * stpcpy(char *dst, const char *src) {
- const size_t len = strlen (src);
- return (char *) memcpy (dst, src, len + 1) + len;
- }
- /*
- as->beginPacketTCP();
- as->write("CONNECT\n");
- as->write("login:");
- as->write(conn->username);
- as->write("\npasscode:");
- as->write(conn->password);
- as->write( (byte *) "\n\n\0",3);
- // as.write( (byte *) "CONNECT\nlogin:\npasscode:\n\n\0",27);
- as->send();
- */
Add Comment
Please, Sign In to add comment