package handler import ( "encoding/xml" "fmt" "io/ioutil" "log" "net/http" "oktopUSP/backend/services/acs/internal/auth" "oktopUSP/backend/services/acs/internal/cwmp" "time" "github.com/oleiade/lane" ) func (h *Handler) CwmpHandler(w http.ResponseWriter, r *http.Request) { log.Printf("--> Connection from %s", r.RemoteAddr) defer r.Body.Close() defer log.Printf("<-- Connection from %s closed", r.RemoteAddr) tmp, _ := ioutil.ReadAll(r.Body) body := string(tmp) if h.acsConfig.DebugMode { log.Println("Received message: ", body) } var envelope cwmp.SoapEnvelope xml.Unmarshal(tmp, &envelope) messageType := envelope.Body.CWMPMessage.XMLName.Local log.Println("messageType: ", messageType) var cpe CPE var exists bool w.Header().Set("Server", "Oktopus "+Version) if messageType != "Inform" { if cookie, err := r.Cookie("oktopus"); err == nil { if cpe, exists = h.Cpes[cookie.Value]; !exists { log.Printf("CPE with serial number %s not found", cookie.Value) } log.Printf("CPE with serial number %s found", cookie.Value) } else { fmt.Println("cookie 'oktopus' missing") w.WriteHeader(401) return } } if messageType == "Inform" { var Inform cwmp.CWMPInform xml.Unmarshal(tmp, &Inform) var addr string if r.Header.Get("X-Real-Ip") != "" { addr = r.Header.Get("X-Real-Ip") } else { addr = r.RemoteAddr } sn := Inform.DeviceId.SerialNumber if _, exists := h.Cpes[sn]; !exists { log.Println("New device: " + sn) h.Cpes[sn] = CPE{ SerialNumber: sn, LastConnection: time.Now(), SoftwareVersion: Inform.GetSoftwareVersion(), HardwareVersion: Inform.GetHardwareVersion(), ExternalIPAddress: addr, ConnectionRequestURL: Inform.GetConnectionRequest(), OUI: Inform.DeviceId.OUI, Queue: lane.NewQueue(), DataModel: Inform.GetDataModelType(), } h.pub(NATS_CWMP_SUBJECT_PREFIX+sn+".info", tmp) } log.Printf("Received an Inform from device %s withEventCodes %s", addr, Inform.GetEvents()) expiration := time.Now().AddDate(0, 0, 1) cookie := http.Cookie{Name: "oktopus", Value: sn, Expires: expiration} http.SetCookie(w, &cookie) //data, _ := xml.Marshal(cwmp.InformResponse(envelope.Header.Id)) fmt.Fprintf(w, cwmp.InformResponse(envelope.Header.Id)) } else if messageType == "TransferComplete" { } else if messageType == "GetRPC" { } else { if len(body) == 0 { log.Println("Got Empty Post") } if cpe.Waiting != nil { log.Println("ACS was waiting for a response from the CPE, now received something") var e cwmp.SoapEnvelope xml.Unmarshal([]byte(body), &e) log.Println("Kind of envelope: ", e.KindOf()) if e.KindOf() == "GetParameterNamesResponse" { log.Println("Receive GetParameterNamesResponse from CPE:", cpe.SerialNumber) msgAnswer(cpe.Waiting.Callback, cpe.Waiting.Time, h.acsConfig.DeviceAnswerTimeout, tmp) } else if e.KindOf() == "GetParameterValuesResponse" { log.Println("Receive GetParameterValuesResponse from CPE:", cpe.SerialNumber) msgAnswer(cpe.Waiting.Callback, cpe.Waiting.Time, h.acsConfig.DeviceAnswerTimeout, tmp) } else if e.KindOf() == "SetParameterValuesResponse" { log.Println("Receive SetParameterValuesResponse from CPE:", cpe.SerialNumber) msgAnswer(cpe.Waiting.Callback, cpe.Waiting.Time, h.acsConfig.DeviceAnswerTimeout, tmp) } else if e.KindOf() == "Fault" { log.Println("Receive FaultResponse from CPE:", cpe.SerialNumber) msgAnswer(cpe.Waiting.Callback, cpe.Waiting.Time, h.acsConfig.DeviceAnswerTimeout, tmp) log.Println(body) } else { log.Println("Unknown message type") log.Println("Body:", body) msgAnswer(cpe.Waiting.Callback, cpe.Waiting.Time, h.acsConfig.DeviceAnswerTimeout, tmp) } cpe.Waiting = nil } else { log.Println("CPE was not waiting for a response") } log.Printf("CPE %s Queue size: %d", cpe.SerialNumber, cpe.Queue.Size()) if cpe.Queue.Size() > 0 { req := cpe.Queue.Dequeue().(Request) cpe.Waiting = &req log.Println("Sending request to CPE:", req.Id) w.Header().Set("Connection", "keep-alive") w.Write(req.CwmpMsg) } else { w.Header().Set("Connection", "close") w.WriteHeader(204) } } cpe.LastConnection = time.Now() h.Cpes[cpe.SerialNumber] = cpe } func (h *Handler) ConnectionRequest(cpe CPE) error { log.Println("--> ConnectionRequest, CPE: ", cpe.SerialNumber) // log.Println("ConnectionRequestURL: ", cpe.ConnectionRequestURL) // log.Println("ConnectionRequestUsername: ", cpe.Username) // log.Println("ConnectionRequestPassword: ", cpe.Password) ok, err := auth.Auth(h.acsConfig.ConnReqUsername, h.acsConfig.ConnReqPassword, cpe.ConnectionRequestURL) if !ok { cpe.Queue.Dequeue() log.Println("Error while authenticating to CPE, err:", err) } else { log.Println("<-- Successfully authenticated to CPE", cpe.SerialNumber) } return err } func msgAnswer( callback chan []byte, timeMsgWasSent time.Time, timeOut time.Duration, msgAnswer []byte, ) { if time.Since(timeMsgWasSent) > timeOut { log.Println("CPE took too long to answer the request, the message will be discarded") } else { callback <- msgAnswer } }