Skip to content
Snippets Groups Projects
Commit 29adac82 authored by Rich Adam's avatar Rich Adam
Browse files

Separate server/client code and update README.md

parent 101fa59c
No related branches found
No related tags found
No related merge requests found
...@@ -4,8 +4,42 @@ Source Specific Multicast (SSM) custom sender and receiver, used to join and lea ...@@ -4,8 +4,42 @@ Source Specific Multicast (SSM) custom sender and receiver, used to join and lea
## Receiver ## Receiver
go run ssm.go 193.17.9.3%232.223.222.1:4099 -i tun3 go run ssmc.go 10.10.250.2%232.2.3.2:4099 -i tun3
The first packet will be displayed with it's index number for example:
`S: 18939904`
Each packet received thereafter will be represented by one of the following characters:
! : Packet with the correct next index sequence.
< : Packet index is less than the previous index.
> : Packet index is greater than the previous index.
When the size of the packet changes this will be represented by "PS[new size]".
Should the index ever be less than zero the end of stream will be reported with `EOS` followed by the last index.
Example:
```
neteam@amt4:~/go/src/ssm$ go run receiver/ssmc.go 10.10.250.2%232.2.3.2:4099 -i ens4
Server listening on UDP port 4099
Joining multicast (S,G)=10.10.250.2,232.2.3.2 w/iface ens4
S: 48PS[1470]!!!!!!!!!!!!!!!!!!!!!![4pps]!!!!!!!!!!!!EOS [i:-82]
```
## Sender ## Sender
go run ssmd.go 232.223.222.1:4099 go run ssmd.go 10.10.250.2%232.2.3.2:4099
Each packet sent will be represented by !
When the sent packet size changes this will be represented by "PS[new size]".
Example:
```
neteam@amt1:~/go/src/ssm$ go run sender/ssmd.go 10.10.250.2%232.2.3.2:4711
!PS[64]!!!!!!PS[66]!PS[115]!PS[126]!PS[92]!PS[66]!PS[64]!!!!!!PS[66]!PS[115]
```
package main
import (
//"encoding/binary"
"encoding/binary"
"fmt"
"net"
"os"
//"runtime"
"regexp"
"time"
"golang.org/x/net/ipv4"
)
func usage() {
fmt.Println("USAGE: ssm <source>%<group>:<port>")
os.Exit(0)
}
func main() {
arguments := os.Args
if len(arguments) < 2 {
usage()
}
/* Process the SSM group join argument */
ssmarg := arguments[1]
re := regexp.MustCompile("^(.*)%(.*):([0-9]+)$")
if re.MatchString(ssmarg) == false {
usage()
}
ssm := re.FindAllStringSubmatch(ssmarg, -1)[0]
source := ssm[1]
group := ssm[2]
port := ssm[3]
var bindif string
allnets, _ := net.Interfaces()
if len(allnets) == 0 {
fmt.Printf("Did not find any network interfaces\n")
return
} else if len(allnets) == 1 {
// Only one interface available so use that.
bindif = allnets[0].Name
} else {
bindif = allnets[1].Name
}
if len(arguments) == 4 {
switch arguments[2] {
case "-i":
bindif = arguments[3]
default:
fmt.Printf("INVALID ARG: %v\n", arguments[2])
usage()
}
}
ssmif, err := net.InterfaceByName(bindif)
if err != nil {
fmt.Printf("Could not bind to interface '%v'\n", bindif)
return
}
c, err := net.ListenPacket("udp4", "0.0.0.0:"+port)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Server listening on UDP port %v\nJoining multicast (S,G)=%v,%v w/iface %v\n", port, source, group, bindif)
defer c.Close()
p := ipv4.NewPacketConn(c)
ssmsource := net.UDPAddr{IP: net.ParseIP(source)}
ssmgroup := net.UDPAddr{IP: net.ParseIP(group)}
if err := p.JoinSourceSpecificGroup(ssmif, &ssmgroup, &ssmsource); err != nil {
// error handling
fmt.Println(err)
return
}
b := make([]byte, 9000)
var index int32
var last_index int32
index = 0
last_index = 0
first_packet := true
packet_count := 0
var stream_start time.Time
packetSize := 0
for {
n, _, _, err := p.ReadFrom(b)
if err != nil {
// error handling
fmt.Println(err)
return
}
if n != 0 {
packet_count++
index = int32(binary.BigEndian.Uint32(b[0:4]))
if index < 0 {
// end of stream
fmt.Printf("!EOS [i:%v]\n", index)
first_packet = true
packet_count = 0
last_index = 0
index = 0
continue
}
if first_packet {
fmt.Printf("S: %v", index)
first_packet = false
stream_start = time.Now()
} else if index == (last_index + 1) {
fmt.Printf("\033[32m!\033[0m")
} else if index < last_index {
fmt.Printf("\033[34m<\033[0m")
} else if index > (last_index + 1) {
fmt.Printf("\033[36m>\033[0m")
} else {
fmt.Printf("\033[31m.\033[0m")
}
last_index = index
if n != packetSize {
fmt.Printf("PS[%v]", n)
packetSize = n
}
if time.Since(stream_start)/time.Second >= 5 {
fmt.Printf("[%vpps]", packet_count/5)
stream_start = time.Now()
packet_count = 0
}
} else {
break
}
}
if err := p.LeaveSourceSpecificGroup(ssmif, &ssmgroup, &ssmsource); err != nil {
// error handling
fmt.Println(err)
return
}
}
package main
import (
//"encoding/binary"
"encoding/hex"
"fmt"
"log"
"net"
"os"
"regexp"
"time"
"golang.org/x/net/ipv4"
)
func usage() {
fmt.Println("USAGE: ssmd <source>%<group>:<port>")
os.Exit(0)
}
func main() {
arguments := os.Args
if len(arguments) < 2 {
usage()
}
/* Process the SSM group join argument */
ssmarg := arguments[1]
re := regexp.MustCompile("^(.*)%(.*):([0-9]+)$")
if re.MatchString(ssmarg) == false {
usage()
}
ssm := re.FindAllStringSubmatch(ssmarg, -1)[0]
source := ssm[1]
group := ssm[2]
port := ssm[3]
dst, err := net.ResolveUDPAddr("udp", group+":"+port)
if err != nil {
log.Fatal(err)
}
//dst := &net.UDPAddr{IP: net.ParseIP(group), Port: }
src, err := net.ListenPacket("udp4", source+":55214")
if err != nil {
log.Fatal(err)
}
defer src.Close()
p := ipv4.NewPacketConn(src)
p.SetTOS(0x0)
p.SetMulticastTTL(32)
data := make([][]byte, 11)
data[0], _ = hex.DecodeString("0121000000000000000000000000000000000000f0000000a0000000000000000000000399d20000000000000000000000000a0afa0254534c2d5445522d3100")
data[1], _ = hex.DecodeString("0121000000000000000000000000000000000000f0000000a0000000000000000000000399d20000000000000000000000000a0afa0254534c2d5445522d3100")
data[2], _ = hex.DecodeString("0121000000000000000000000000000000000000f0000000a0000000000000000000000399d20000000000000000000000000a0afa0254534c2d5445522d3100")
data[3], _ = hex.DecodeString("0121000000000000000000000000000000000000f0000000a0000000000000000000000399d20000000000000000000000000a0afa0254534c2d5445522d3100")
data[4], _ = hex.DecodeString("0121000000000000000000000000000000000000f0000000a0000000000000000000000399d20000000000000000000000000a0afa0254534c2d5445522d3100")
data[5], _ = hex.DecodeString("0121000000000000000000000000000000000000f0000000a0000000000000000000000399d20000000000000000000000000a0afa0254534c2d5445522d3100")
data[6], _ = hex.DecodeString("012099d20000000000000000000000000a0afa02f00000012000000000aaaaaa000000000000001010ffffff000005dc00000000000a54534c2d5445522d31000000")
data[7], _ = hex.DecodeString("010199d20000000000000000000000000a0afa02f000000220000001002aaaaaea660000c00000000000000099d20000000000000000000000000a0afa020000003105020000003162e7b95400000000000000000000400000000000e8dfde0212670000000186a0c654534c2d5445522d3100")
data[8], _ = hex.DecodeString("012099d20000000000000000000000000a0afa02f00000032000000100aaaaaaea6600000000001010ffffff000005dc00000000000a54534c2d5445522d310000000104eb070000000000000000000000000a0afd030104ee4c0000000000000000000000000a0aff030104eb150000000000000000000000000a00000a")
data[9], _ = hex.DecodeString("010199d20000000000000000000000000a0afa02f000000420000002002aaaaaea660000c00000010000000099d20000000000000000000000000a0afa020000001a05700000001a03e80000000000000000000000003e286f7927b0")
data[10], _ = hex.DecodeString("012099d20000000000000000000000000a0afa02f00000052000000200aaaaaaea6600000000001010ffffff000005dc00000000000a54534c2d5445522d31000000")
packetSize := 0
packetId := 0
for {
fmt.Printf("!")
n, _ := p.WriteTo(data[packetId], nil, dst)
if n != packetSize {
fmt.Printf("PS[%v]", n)
packetSize = n
}
if packetId == 10 {
packetId = 0
} else {
packetId++
}
time.Sleep(500 * time.Millisecond)
}
}
package main
import (
//"encoding/binary"
"fmt"
"net"
"os"
"encoding/binary"
//"runtime"
"time"
"regexp"
"golang.org/x/net/ipv4"
)
func usage() {
fmt.Println("USAGE: ssm <source>%<group>:<port>\n")
os.Exit(0)
}
func main() {
arguments := os.Args
if len(arguments) < 2 {
usage()
}
/* Process the SSM group join argument */
ssmarg := arguments[1]
re := regexp.MustCompile("^(.*)%(.*):([0-9]+)$")
if re.MatchString(ssmarg) == false {
usage()
}
ssm := re.FindAllStringSubmatch(ssmarg, -1)[0]
source := ssm[1]
group := ssm[2]
port := ssm[3]
var bindif string
allnets, _ := net.Interfaces()
if(len(allnets) == 0) {
fmt.Printf("Did not find any network interfaces\n")
return
} else if (len(allnets) == 1) {
// Only one interface available so use that.
bindif = allnets[0].Name
} else {
bindif = allnets[1].Name
}
if len(arguments) == 4 {
switch(arguments[2]) {
case "-i":
bindif = arguments[3]
default:
fmt.Printf("INVALID ARG: %v\n", arguments[2])
usage()
}
}
ssmif, err := net.InterfaceByName(bindif)
if err != nil {
fmt.Printf("Could not bind to interface '%v'\n", bindif)
return
}
c, err := net.ListenPacket("udp4", "0.0.0.0:" + port)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Server listening on UDP port %v\nJoining multicast (S,G)=%v,%v w/iface %v\n", port, source, group, bindif)
defer c.Close()
p := ipv4.NewPacketConn(c)
ssmsource := net.UDPAddr{IP: net.ParseIP(source)}
ssmgroup := net.UDPAddr{IP: net.ParseIP(group)}
if err := p.JoinSourceSpecificGroup(ssmif, &ssmgroup, &ssmsource); err != nil {
// error handling
fmt.Println(err)
return
}
b := make([]byte, 1500)
var index int32
var last_index int32
index = 0
last_index = 0
first_packet := true
packet_count := 0
var stream_start time.Time
for {
n, _, _, err := p.ReadFrom(b)
if err != nil {
// error handling
fmt.Println(err)
return
}
if n != 0 {
packet_count++
index = int32(binary.BigEndian.Uint32(b[0:4]))
if index < 0 {
// end of stream
fmt.Printf("!EOS [i:%v]\n", index)
first_packet = true
packet_count = 0
last_index = 0
index = 0
continue
}
if first_packet {
fmt.Printf("S: %v", index)
first_packet = false
stream_start = time.Now()
} else if index == (last_index + 1){
fmt.Printf("\033[32m!\033[0m")
} else if index < last_index {
fmt.Printf("\033[34m<\033[0m")
} else if index > (last_index + 1) {
fmt.Printf("\033[36m>\033[0m")
} else {
fmt.Printf("\033[31m.\033[0m")
}
last_index = index
if time.Since(stream_start)/time.Second >= 5 {
fmt.Printf("[%vpps]", packet_count/5)
stream_start = time.Now()
packet_count = 0
}
} else {
break
}
}
if err := p.LeaveSourceSpecificGroup(ssmif, &ssmgroup, &ssmsource); err != nil {
// error handling
fmt.Println(err)
return
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment