/* * Video On Demand Samples * * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * You may also obtain this software under a propriety license from Microchip. * Please contact Microchip for further information. * */ #include #include #include #include #include #include #include #include #include #include #include #include "Console.h" /*----------------------------------------------------------*/ /*! \brief Private structure used by UdpStream component. */ /*----------------------------------------------------------*/ typedef struct localVar_tag { ///Socket handle. int sock; ///Target port. int port; ///Target IP address as zero terminated string. char targetIpAddress[32]; ///SocketAddress structure to address remote node. struct sockaddr_in destination; ///Helper variable to suppress a lot of error messages. bool errorMode; } localVar_t; static localVar_t udpLocal; bool UdpStream_Init( const char *targetIp, int targetPort ) { if( ( NULL == targetIp ) || ( 0 == targetPort ) ) { return false; } ConsolePrintf( PRIO_HIGH, "Sending UDP stream to IP:'%s', port:%d\n", targetIp, targetPort ); strcpy( udpLocal.targetIpAddress, targetIp ); udpLocal.port = targetPort; udpLocal.errorMode = false; memset( &udpLocal.destination, 0, sizeof( udpLocal.destination ) ); /* Default send address */ udpLocal.destination.sin_family = AF_INET; udpLocal.destination.sin_addr.s_addr = inet_addr( udpLocal.targetIpAddress ); udpLocal.destination.sin_port = htons( udpLocal.port ); if( ( udpLocal.sock = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) < 0 ) { ConsolePrintf( PRIO_ERROR, RED"Failed to create socket"RESETCOLOR"\n" ); return false; } #if defined (SO_REUSEADDR) && defined (SO_REUSEPORT) int one = 1; setsockopt(udpLocal.sock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &one, sizeof(one)); #endif /* set default destination */ setsockopt( udpLocal.sock, IPPROTO_IP, IP_MULTICAST_IF, &udpLocal.destination, sizeof( udpLocal.destination ) ); // this call is what allows broadcast packets to be sent: int enableSocketFlag = 1; if( setsockopt( udpLocal.sock, SOL_SOCKET, SO_BROADCAST, &enableSocketFlag, sizeof( enableSocketFlag ) ) < 0 ) { ConsolePrintf( PRIO_ERROR, RED"setsockopt (SO_BROADCAST) failed"RESETCOLOR"\n" ); return false; } int ttl = 5; if (!(setsockopt( udpLocal.sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)))) { ConsolePrintf( PRIO_HIGH, "TTL set successfully to %d\n", ttl ); } else { ConsolePrintf( PRIO_ERROR, "Error setting TTL: %s\n", strerror(errno)); } return true; } void UdpStream_Close() { close( udpLocal.sock ); } bool UdpStream_Send( const uint8_t *data, uint32_t length ) { int is_length = sendto( udpLocal.sock, data, length, 0, ( struct sockaddr * )&udpLocal.destination, sizeof( udpLocal.destination ) ); if( is_length != length ) { if( !udpLocal.errorMode ) { udpLocal.errorMode = true; ConsolePrintf( PRIO_ERROR, RED"Send failed; shall len = %d; is length = %d"RESETCOLOR"\n", length, is_length ); } return false; } else udpLocal.errorMode = false; return true; }