]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - support/sdk/c/sf/sfsource.c
moving from sdk/c
[tinyos-2.x.git] / support / sdk / c / sf / sfsource.c
diff --git a/support/sdk/c/sf/sfsource.c b/support/sdk/c/sf/sfsource.c
new file mode 100644 (file)
index 0000000..24df960
--- /dev/null
@@ -0,0 +1,161 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sfsource.h"
+
+int saferead(int fd, void *buffer, int count)
+{
+  int actual = 0;
+
+  while (count > 0)
+    {
+      int n = read(fd, buffer, count);
+
+      if (n == -1 && errno == EINTR)
+       continue;
+      if (n == -1)
+       return -1;
+      if (n == 0)
+       return actual;
+
+      count -= n;
+      actual += n;
+      buffer = (char*)buffer + n;
+    }
+  return actual;
+}
+
+int safewrite(int fd, const void *buffer, int count)
+{
+  int actual = 0;
+
+  while (count > 0)
+    {
+      int n = write(fd, buffer, count);
+
+      if (n == -1 && errno == EINTR)
+       continue;
+      if (n == -1)
+       return -1;
+
+      count -= n;
+      actual += n;
+      buffer = (char*)buffer + n;
+    }
+  return actual;
+}
+
+int open_sf_source(const char *host, int port)
+/* Returns: file descriptor for serial forwarder at host:port
+ */
+{
+  int fd = socket(AF_INET, SOCK_STREAM, 0);
+  struct hostent *entry;
+  struct sockaddr_in addr;
+
+  if (fd < 0)
+    return fd;
+
+  entry = gethostbyname(host);
+  if (!entry)
+    {
+      close(fd);
+      return -1;
+    }      
+
+  addr.sin_family = entry->h_addrtype;
+  memcpy(&addr.sin_addr, entry->h_addr, entry->h_length);
+  addr.sin_port = htons(port);
+  if (connect(fd, (struct sockaddr *)&addr, sizeof addr) < 0)
+    {
+      close(fd);
+      return -1;
+    }
+
+  if (init_sf_source(fd) < 0)
+    {
+      close(fd);
+      return -1;
+    }
+
+  return fd;
+}
+
+int init_sf_source(int fd)
+/* Effects: Checks that fd is following the TinyOS 2.0 serial forwarder 
+     protocol. Use this if you obtain your file descriptor from some other
+     source than open_sf_source (e.g., you're a server)
+   Returns: 0 if it is, -1 otherwise
+ */
+{
+  char check[2], us[2];
+  int version;
+
+  /* Indicate version and check if a TinyOS 2.0 serial forwarder on the
+     other end */
+  us[0] = 'U'; us[1] = ' ';
+  if (safewrite(fd, us, 2) != 2 ||
+      saferead(fd, check, 2) != 2 ||
+      check[0] != 'U')
+    return -1;
+
+  version = check[1];
+  if (us[1] < version)
+    version = us[1];
+
+  /* Add other cases here for later protocol versions */
+  switch (version)
+    {
+    case ' ': break;
+    default: return -1; /* not a valid version */
+    }
+
+  return 0;
+}
+
+void *read_sf_packet(int fd, int *len)
+/* Effects: reads packet from serial forwarder on file descriptor fd
+   Returns: the packet read (in newly allocated memory), and *len is
+     set to the packet length, or NULL for failure
+*/
+{
+  unsigned char l;
+  void *packet;
+
+  if (saferead(fd, &l, 1) != 1)
+    return NULL;
+
+  packet = malloc(l);
+  if (!packet)
+    return NULL;
+
+  if (saferead(fd, packet, l) != l)
+    {
+      free(packet);
+      return NULL;
+    }
+  *len = l;
+  
+  return packet;
+}
+
+int write_sf_packet(int fd, const void *packet, int len)
+/* Effects: writes len byte packet to serial forwarder on file descriptor
+     fd
+   Returns: 0 if packet successfully written, -1 otherwise
+*/
+{
+  unsigned char l = len;
+
+  if (safewrite(fd, &l, 1) != 1 ||
+      safewrite(fd, packet, l) != l)
+    return -1;
+
+  return 0;
+}