Advertisement
Guest User

Untitled

a guest
Oct 24th, 2016
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 8.15 KB | None | 0 0
  1.  
  2. package hub
  3.  
  4. import (
  5.     "fmt"
  6.     "net/http"
  7.     "io/ioutil"
  8.     "encoding/json"
  9.     "appengine"
  10.     "appengine/channel"
  11.     "dhcp"
  12.     "repository"
  13.     "encryption"
  14. )
  15.  
  16. // api error constants.
  17. const (
  18.     InternalServerError              = 600
  19.     ConnectAddressAllocationError    = 700
  20.     ConnectChannelInitializeError    = 701
  21.     ConnectIdentitySerializeError    = 702
  22.     ConnectEncryptionError           = 703
  23.     ForwardHttpStreamError           = 800
  24.     ForwardDeserializeError          = 801
  25.     ForwardDecryptionError           = 802
  26.     ForwardDeserializeIdentityError  = 803
  27.     ForwardIdentityVerificationError = 804
  28.     ForwardSerializeError            = 805  
  29. )
  30. var errorText = map[int16] string {
  31.     InternalServerError              : "internal server error.",
  32.     ConnectAddressAllocationError    : "unable to allocate address.",
  33.     ConnectChannelInitializeError    : "unable to initialize data channel.",
  34.     ConnectEncryptionError           : "unable to encrypt identity.",
  35.     ForwardHttpStreamError           : "unable to read from http input stream.",
  36.     ForwardDeserializeError          : "unable to deserialize user request.",
  37.     ForwardDecryptionError           : "unable to decrypt user identity",
  38.     ForwardDeserializeIdentityError  : "unable to deserialize identity",
  39.     ForwardIdentityVerificationError : "unable to verify user identity.",
  40.     ForwardSerializeError            : "unable to serialize forwarded message.",
  41. }
  42.  
  43. type Error struct {
  44.     Code    int16        `json:"code"`
  45.     Message string       `json:"message"`
  46. }
  47. type RequestError struct {
  48.     Error   Error        `json:"error"`
  49. }
  50. type RequestOk struct {
  51.     Data    interface {} `json:"data"`
  52. }
  53.  
  54. func init() {
  55.     http.Handle("/connect", Cors(http.HandlerFunc(connect)))
  56.     http.Handle("/forward", Cors(http.HandlerFunc(forward)))
  57. }
  58.  
  59. // cross origin middleware.
  60. func Cors(next http.Handler) http.Handler {
  61.     fc := func(w http.ResponseWriter, r *http.Request) {
  62.         w.Header().Set("Access-Control-Allow-Origin", "*")
  63.         w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
  64.         w.Header().Set("Access-Control-Allow-Headers", "Origin, Accept, X-Requested-With, Content-Type")
  65.         if r.Method == "OPTIONS" {
  66.             w.WriteHeader(200)
  67.             w.Write([]byte(""))
  68.             return
  69.         }
  70.         next.ServeHTTP(w, r)
  71.     }
  72.     return http.HandlerFunc(fc)
  73. }
  74.  
  75. // writes a standard api json error on the given response.
  76. func WriteError (w http.ResponseWriter, code int16) {
  77.     output := RequestError {
  78.         Error: Error {
  79.             Code    : code,
  80.             Message : errorText[code],
  81.         },
  82.     }
  83.     if json, err := json.MarshalIndent(output, "", " "); err != nil {
  84.         w.Header().Set("Content-Type", "application/json")
  85.         w.WriteHeader(500)
  86.         w.Write([]byte(fmt.Sprintf("{error:{ \"code\": %d, \"message\": \"%s\" }}",
  87.             InternalServerError,
  88.             errorText[InternalServerError],
  89.         )))
  90.     } else {
  91.         w.Header().Set("Content-Type", "application/json")
  92.         w.WriteHeader(500)
  93.         w.Write(json)
  94.     }
  95. }
  96.  
  97. // writes a standard api json ok on the given response.
  98. func WriteOk (w http.ResponseWriter, data interface {}) {
  99.     output := RequestOk {
  100.         Data: data,
  101.     }
  102.     if json, err := json.MarshalIndent(output, "", " "); err != nil {
  103.         w.Header().Set("Content-Type", "application/json")
  104.         w.WriteHeader(500)
  105.         w.Write([]byte(fmt.Sprintf("{error:{ \"code\": %d, \"message\": \"%s\" }}",
  106.             InternalServerError,
  107.             errorText[InternalServerError],
  108.         )))
  109.     } else {    
  110.         w.Header().Set("Content-Type", "application/json")
  111.         w.WriteHeader(200)
  112.         w.Write(json)
  113.     }
  114. }
  115.  
  116. // connection identity. generated on connect
  117. // and passed on forward, this struct is encrypted
  118. // between client and server and used to verify
  119. // the identity of the user forwarding messages.
  120. type Identity struct {
  121.     RemoteAddr string `json:"remoteAddr"`
  122.     Address    string `json:"address"`
  123. }
  124.  
  125. type ConnectResponse struct {
  126.     Channel   string `json:"channel"`
  127.     Identity  string `json:"identity"`
  128.     Address   string `json:"address"`
  129. }
  130.  
  131. // creates a new connection to this hub.
  132. func connect (w http.ResponseWriter, r *http.Request) {
  133.     context    := appengine.NewContext(r)
  134.     repository := repository.NewAppEngineRepository  (context)
  135.     allocator  := dhcp.NewVirtualAddressAllocator    (repository)
  136.     encryption := encryption.NewAesEncryptionProvider(repository)
  137.  
  138.     // allocate new address.
  139.     if address, err := allocator.Next(); err != nil {
  140.         WriteError(w, ConnectAddressAllocationError)
  141.     } else {
  142.  
  143.         // create new channel.
  144.         if channel_token, err := channel.Create(context, address); err != nil {
  145.             WriteError(w, ConnectChannelInitializeError)
  146.         } else {
  147.  
  148.             // create identity for user.
  149.             if identity, err := json.Marshal( Identity {RemoteAddr: r.RemoteAddr, Address: address}); err != nil {
  150.                 WriteError(w, ConnectIdentitySerializeError)
  151.             } else {
  152.  
  153.                 // encrypt the user identity.
  154.                 if identity_token, err := encryption.Encrypt(string(identity)); err != nil {
  155.                     WriteError(w, ConnectEncryptionError)
  156.                 } else {
  157.  
  158.                     // respond.
  159.                     WriteOk(w, ConnectResponse {
  160.                         Channel : channel_token,
  161.                         Identity: identity_token,
  162.                         Address : address,
  163.                     })
  164.                 }
  165.             }
  166.         }
  167.     }
  168. }
  169.  
  170. type ForwardRequest struct {
  171.     Identity string  `json:"identity"`
  172.     To       string  `json:"to"`
  173.     Data     string  `json:"data"`
  174. }
  175. type ForwardResponse struct {
  176.     Ok        bool   `json:"ok"`
  177. }
  178. type ForwardOutput struct {
  179.     From     string `json:"from"`
  180.     To       string `json:"to"`
  181.     Data     string `json:"data"`
  182. }
  183.  
  184. // forwards a request onto another user connected to the hub.
  185. func forward(w http.ResponseWriter, r *http.Request) {
  186.     context    := appengine.NewContext(r)
  187.     repository := repository.NewAppEngineRepository  (context)
  188.     encryption := encryption.NewAesEncryptionProvider(repository)
  189.    
  190.     // read http content.
  191.     defer r.Body.Close()
  192.     if content, err := ioutil.ReadAll(r.Body); err != nil {
  193.         WriteError(w, ForwardHttpStreamError)
  194.     } else {
  195.  
  196.         // deserialize message.
  197.         var request ForwardRequest
  198.         if err := json.Unmarshal(content, &request); err != nil {
  199.             WriteError(w, ForwardDeserializeError)
  200.         } else {
  201.  
  202.             // decrypt identity token.
  203.             if identity_token, err := encryption.Decrypt(request.Identity); err != nil {
  204.                  WriteError(w, ForwardDecryptionError)
  205.             } else {
  206.                
  207.                 // deserialize identity from token.
  208.                 var identity Identity
  209.                 if err := json.Unmarshal([]byte(identity_token), &identity); err != nil {
  210.                     WriteError(w, ForwardDeserializeIdentityError)
  211.                 } else {
  212.  
  213.                     // validate request and identity remote address.
  214.                     if identity.RemoteAddr != r.RemoteAddr {
  215.                         WriteError(w, ForwardIdentityVerificationError)
  216.                     } else {
  217.  
  218.                         // create forwarded message.
  219.                         message := ForwardOutput {
  220.                             From   : identity.Address,
  221.                             To     : request.To,
  222.                             Data   : request.Data,
  223.                         }
  224.                         if output, err := json.Marshal(message); err != nil {
  225.                             WriteError(w, ForwardSerializeError)
  226.                         } else {
  227.  
  228.                             // emit to channel and respond ok.
  229.                             channel.Send(context, request.To, string(output))
  230.                             WriteOk(w, ForwardResponse {  Ok: true, })
  231.                         }
  232.                     }
  233.                 }
  234.             }
  235.         }
  236.     }
  237. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement