mirror of
https://github.com/mainflux/mainflux.git
synced 2025-04-27 13:48:49 +08:00

* Add SMPP notifier Signed-off-by: Ivan Milosevic <iva@blokovi.com> * fix readme remove env file Signed-off-by: Ivan Milosevic <iva@blokovi.com> * resolve conversations Signed-off-by: Ivan Milosevic <iva@blokovi.com> * Remove debug log Signed-off-by: Ivan Milosevic <iva@blokovi.com> * Rename transmiter and transformer fields in struct Signed-off-by: Ivan Milosevic <iva@blokovi.com> * fix typo Signed-off-by: Ivan Milosevic <iva@blokovi.com>
162 lines
3.3 KiB
Go
162 lines
3.3 KiB
Go
// Copyright 2015 go-smpp authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
package smpp
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"crypto/tls"
|
|
"errors"
|
|
"io"
|
|
"net"
|
|
"sync"
|
|
|
|
"github.com/fiorix/go-smpp/smpp/pdu"
|
|
)
|
|
|
|
var (
|
|
// ErrNotConnected is returned on attempts to use a dead connection.
|
|
ErrNotConnected = errors.New("not connected")
|
|
|
|
// ErrNotBound is returned on attempts to use a Transmitter,
|
|
// Receiver or Transceiver before calling Bind.
|
|
ErrNotBound = errors.New("not bound")
|
|
|
|
// ErrTimeout is returned when we've reached timeout while waiting for response.
|
|
ErrTimeout = errors.New("timeout waiting for response")
|
|
)
|
|
|
|
// Conn is an SMPP connection.
|
|
type Conn interface {
|
|
Reader
|
|
Writer
|
|
Closer
|
|
}
|
|
|
|
// Reader is the interface that wraps the basic Read method.
|
|
type Reader interface {
|
|
// Read reads PDU binary data off the wire and returns it.
|
|
Read() (pdu.Body, error)
|
|
}
|
|
|
|
// Writer is the interface that wraps the basic Write method.
|
|
type Writer interface {
|
|
// Write serializes the given PDU and writes to the connection.
|
|
Write(w pdu.Body) error
|
|
}
|
|
|
|
// Closer is the interface that wraps the basic Close method.
|
|
type Closer interface {
|
|
// Close terminates the connection.
|
|
Close() error
|
|
}
|
|
|
|
// Dial dials to the SMPP server and returns a Conn, or error.
|
|
// TLS is only used if provided.
|
|
func Dial(addr string, TLS *tls.Config) (Conn, error) {
|
|
if addr == "" {
|
|
addr = "localhost:2775"
|
|
}
|
|
fd, err := net.Dial("tcp", addr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if TLS != nil {
|
|
fd = tls.Client(fd, TLS)
|
|
}
|
|
c := &conn{
|
|
rwc: fd,
|
|
r: bufio.NewReader(fd),
|
|
w: bufio.NewWriter(fd),
|
|
}
|
|
return c, nil
|
|
}
|
|
|
|
// conn provides the basics of a single client connection and
|
|
// implements the Conn interface.
|
|
type conn struct {
|
|
rwc net.Conn
|
|
r *bufio.Reader
|
|
w *bufio.Writer
|
|
}
|
|
|
|
// Read implements the Conn interface.
|
|
func (c *conn) Read() (pdu.Body, error) {
|
|
return pdu.Decode(c.r)
|
|
}
|
|
|
|
// Write implements the Conn interface.
|
|
func (c *conn) Write(w pdu.Body) error {
|
|
var b bytes.Buffer
|
|
err := w.SerializeTo(&b)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = io.Copy(c.w, &b)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return c.w.Flush()
|
|
}
|
|
|
|
// Close implements the Conn interface.
|
|
func (c *conn) Close() error {
|
|
return c.rwc.Close()
|
|
}
|
|
|
|
// connSwitch implements the Conn interface but allows switching
|
|
// the actual Conn object it wraps.
|
|
//
|
|
// If no Conn is available, any attempt to Read/Write/Close
|
|
// returns ErrNotConnected.
|
|
type connSwitch struct {
|
|
mu sync.Mutex
|
|
c Conn
|
|
}
|
|
|
|
// Set sets the underlying Conn with the given one.
|
|
// If we hold a Conn already, it will be closed before switching over.
|
|
func (cs *connSwitch) Set(c Conn) {
|
|
cs.mu.Lock()
|
|
if cs.c != nil {
|
|
cs.c.Close()
|
|
}
|
|
cs.c = c
|
|
cs.mu.Unlock()
|
|
}
|
|
|
|
// Read implements the Conn interface.
|
|
func (cs *connSwitch) Read() (pdu.Body, error) {
|
|
cs.mu.Lock()
|
|
conn := cs.c
|
|
cs.mu.Unlock()
|
|
if conn == nil {
|
|
return nil, ErrNotConnected
|
|
}
|
|
return conn.Read()
|
|
}
|
|
|
|
// Write implements the Conn interface.
|
|
func (cs *connSwitch) Write(w pdu.Body) error {
|
|
cs.mu.Lock()
|
|
defer cs.mu.Unlock()
|
|
if cs.c == nil {
|
|
return ErrNotConnected
|
|
}
|
|
return cs.c.Write(w)
|
|
}
|
|
|
|
// Close implements the Conn interface.
|
|
func (cs *connSwitch) Close() error {
|
|
cs.mu.Lock()
|
|
defer cs.mu.Unlock()
|
|
if cs.c == nil {
|
|
return ErrNotConnected
|
|
}
|
|
err := cs.c.Close()
|
|
cs.c = nil
|
|
return err
|
|
}
|