]> git.feebdaed.xyz Git - gomehub.git/commitdiff
Adding views, api for authentication, session management
authorseantywork <seantywork@gmail.com>
Thu, 11 Jul 2024 08:31:19 +0000 (17:31 +0900)
committerseantywork <seantywork@gmail.com>
Thu, 11 Jul 2024 08:31:19 +0000 (17:31 +0900)
26 files changed:
ctl/base.go
ctl/config.go
ctl/ctl.go
pkg/auth/auth.go
pkg/auth/integrity.go [new file with mode: 0644]
pkg/auth/oauth2.go
pkg/auth/session.go [new file with mode: 0644]
pkg/com/com.go [new file with mode: 0644]
pkg/dbquery/dbquery.go
pkg/edition/edition_video.go [new file with mode: 0644]
pkg/stream/signal.go
pkg/stream/stream.go
pkg/stream/stream_cctv.go
pkg/stream/stream_peers.go
pkg/stream/stream_video.go [deleted file]
view/content/peers.html [deleted file]
view/etc/cctv_local.html [new file with mode: 0644]
view/etc/peers_p2p.html [new file with mode: 0644]
view/mypage.html [deleted file]
view/mypage/article.html [new file with mode: 0644]
view/mypage/index.html [new file with mode: 0644]
view/mypage/room.html [new file with mode: 0644]
view/mypage/video.html [new file with mode: 0644]
view/org/cctv_local.html [deleted file]
view/org/peers_p2p.html [deleted file]
view/room/index.html [new file with mode: 0644]

index d9826cac6e74d1867fa9e435af60b2969f0d819e..1a402aab8238aad7085d362a25cc54122cf193dd 100644 (file)
@@ -15,19 +15,31 @@ func GetViewSignin(c *gin.Context) {
 
 func GetViewMypage(c *gin.Context) {
 
-       c.HTML(200, "mypage.html", gin.H{})
+       c.HTML(200, "mypage/index.html", gin.H{})
 
 }
 
-func GetViewContentArticle(c *gin.Context) {
+func GetViewMypageArticle(c *gin.Context) {
 
-       c.HTML(200, "content/article.html", gin.H{})
+       c.HTML(200, "mypage/article.html", gin.H{})
+
+}
+
+func GetViewMypageVideo(c *gin.Context) {
+
+       c.HTML(200, "mypage/video.html", gin.H{})
+
+}
+
+func GetViewMypageRoom(c *gin.Context) {
+
+       c.HTML(200, "mypage/room.html", gin.H{})
 
 }
 
-func GetViewContentPeers(c *gin.Context) {
+func GetViewContentArticle(c *gin.Context) {
 
-       c.HTML(200, "content/peers.html", gin.H{})
+       c.HTML(200, "content/article.html", gin.H{})
 
 }
 
@@ -36,3 +48,9 @@ func GetViewContentVideo(c *gin.Context) {
        c.HTML(200, "content/video.html", gin.H{})
 
 }
+
+func GetViewRoom(c *gin.Context) {
+
+       c.HTML(200, "room/index.html", gin.H{})
+
+}
index 503bf65209127569c6846e8d605b8ea5314b5536..38fe7bc4bb6e8e915d9dc362de72c1e1696bbb44 100644 (file)
@@ -13,23 +13,27 @@ type SOLIAGAIN_CONFIG struct {
        ServeAddr   string `yaml:"serveAddr"`
        ServePort   int    `yaml:"servePort"`
        MaxFileSize int64  `yaml:"maxFileSize"`
-       Stream      struct {
+       Com         struct {
+               ChannelPort         int `yaml:"channelPort"`
+               ChannelPortExternal int `yaml:"channelPortExternal"`
+       } `yaml:"channel"`
+       Edition struct {
+               ExtAllowList []string `yaml:"extAllowList"`
+       } `yaml:"edition"`
+       Stream struct {
                TurnServerAddr []struct {
                        Addr string `yaml:"addr"`
                        Id   string `yaml:"id"`
                        Pw   string `yaml:"pw"`
                } `yaml:"turnServerAddr"`
-               PeerSignalAddr         string   `yaml:"peerSignalAddr"`
-               RtcpPLIInterval        int      `yaml:"rtcpPLIInterval"`
-               ExtAllowList           []string `yaml:"extAllowList"`
-               UdpBufferByteSize      int      `yaml:"udpBufferByteSize"`
-               UdpMuxPort             int      `yaml:"udpMuxPort"`
-               UdpEphemeralPortMin    int      `yaml:"udpEphemeralPortMin"`
-               UdpEphemeralPortMax    int      `yaml:"udpEphemeralPortMax"`
-               SignalPort             int      `yaml:"signalPort"`
-               SignalPortExternal     int      `yaml:"signalPortExternal"`
-               RtpReceivePort         int      `yaml:"rtpReceivePort"`
-               RtpReceivePortExternal int      `yaml:"rtpReceivePortExternal"`
+               PeerSignalAddr         string `yaml:"peerSignalAddr"`
+               RtcpPLIInterval        int    `yaml:"rtcpPLIInterval"`
+               UdpBufferByteSize      int    `yaml:"udpBufferByteSize"`
+               UdpMuxPort             int    `yaml:"udpMuxPort"`
+               UdpEphemeralPortMin    int    `yaml:"udpEphemeralPortMin"`
+               UdpEphemeralPortMax    int    `yaml:"udpEphemeralPortMax"`
+               RtpReceivePort         int    `yaml:"rtpReceivePort"`
+               RtpReceivePortExternal int    `yaml:"rtpReceivePortExternal"`
        } `yaml:"stream"`
        Utils struct {
                UseCompress bool `yaml:"useCompress"`
index 5876a6d0dca2176e9cf07fc617ba1a9358dc5fb8..d962173fad4900cf3f337797558b1736fc4bd2e6 100644 (file)
@@ -7,6 +7,8 @@ import (
        "github.com/gin-gonic/contrib/sessions"
        "github.com/gin-gonic/gin"
        pkgauth "github.com/seantywork/sorrylinus-again/pkg/auth"
+       pkgcom "github.com/seantywork/sorrylinus-again/pkg/com"
+       pkgedition "github.com/seantywork/sorrylinus-again/pkg/edition"
        pkgstream "github.com/seantywork/sorrylinus-again/pkg/stream"
        pkgutils "github.com/seantywork/sorrylinus-again/pkg/utils"
 )
@@ -37,6 +39,12 @@ func ConfigureRuntime(e *gin.Engine) {
 
        pkgstream.INTERNAL_URL = CONF.InternalUrl
 
+       pkgcom.CHANNEL_ADDR = CONF.ServeAddr
+       pkgcom.CHANNEL_PORT = fmt.Sprintf("%d", CONF.Com.ChannelPort)
+       pkgcom.CHANNEL_PORT_EXTERNAL = fmt.Sprintf("%d", CONF.Com.ChannelPortExternal)
+
+       pkgedition.EXTENSION_ALLOWLIST = CONF.Edition.ExtAllowList
+
        for i := 0; i < len(CONF.Stream.TurnServerAddr); i++ {
 
                tmp := struct {
@@ -55,17 +63,12 @@ func ConfigureRuntime(e *gin.Engine) {
        pkgstream.PEERS_SIGNAL_PATH = CONF.Stream.PeerSignalAddr
 
        pkgstream.RTCP_PLI_INTERVAL = time.Second * time.Duration(CONF.Stream.RtcpPLIInterval)
-       pkgstream.EXTENSION_ALLOWLIST = CONF.Stream.ExtAllowList
 
        pkgstream.UDP_BUFFER_BYTE_SIZE = CONF.Stream.UdpBufferByteSize
        pkgstream.UDP_MUX_PORT = CONF.Stream.UdpMuxPort
        pkgstream.UDP_EPHEMERAL_PORT_MIN = CONF.Stream.UdpEphemeralPortMin
        pkgstream.UDP_EPHEMERAL_PORT_MAX = CONF.Stream.UdpEphemeralPortMax
 
-       pkgstream.SIGNAL_ADDR = CONF.ServeAddr
-       pkgstream.SIGNAL_PORT = fmt.Sprintf("%d", CONF.Stream.SignalPort)
-       pkgstream.SIGNAL_PORT_EXTERNAL = fmt.Sprintf("%d", CONF.Stream.SignalPortExternal)
-
        pkgstream.RTP_RECEIVE_ADDR = CONF.ServeAddr
        pkgstream.RTP_RECEIVE_PORT = fmt.Sprintf("%d", CONF.Stream.RtpReceivePort)
        pkgstream.RTP_RECEIVE_PORT_EXTERNAL = fmt.Sprintf("%d", CONF.Stream.RtpReceivePortExternal)
@@ -88,23 +91,31 @@ func RegisterRoutes(e *gin.Engine) {
 
        e.GET("/mypage", GetViewMypage)
 
-       e.GET("/content/article/:articleId", GetViewContentArticle)
+       e.GET("/mypage/article", GetViewMypage)
 
-       e.GET("/content/peers/:peersId", GetViewContentPeers)
+       e.GET("/mypage/video", GetViewMypage)
+
+       e.GET("/mypage/room", GetViewMypage)
+
+       e.GET("/content/article/:articleId", GetViewContentArticle)
 
        e.GET("/content/video/:videoId", GetViewContentVideo)
 
+       e.GET("/room/:roomId", GetViewRoom)
+
        // auth
 
        e.GET("/api/oauth2/google/signin", pkgauth.OauthGoogleLogin)
 
        e.GET("/oauth2/google/callback", pkgauth.OauthGoogleCallback)
 
-       // e.POST("/api/auth/user/add", pkgauth.UserAdd)
+       e.POST("/api/auth/user/add", pkgauth.UserAdd)
 
-       // e.GET("/api/auth/signin", pkgauth.Login)
+       e.POST("/api/auth/user/remove", pkgauth.UserRemove)
 
-       // e.GET("/api/auth/signout", pkgauth.Logout)
+       e.GET("/api/auth/signin", pkgauth.Login)
+
+       e.GET("/api/auth/signout", pkgauth.Logout)
 
        pkgauth.InitAuth()
 
@@ -112,12 +123,20 @@ func RegisterRoutes(e *gin.Engine) {
 
        // e.POST("/api/article/upload", pkgedition.PostArticleUpload)
 
-       // e.GET("/api/article/c/:contentId", pkgeditioni.GetArticleContentById)
+       // e.POST("/api/article/delete", pkgedition.PostArticleDelete)
+
+       // e.GET("/api/article/c/:contentId", pkgedition.GetArticleContentById)
 
        // e.POST("/api/image/upload", pkgedition.PostImageUpload)
 
        // e.GET("/api/image/c/:contentId", pkgedition.GetImageContentById)
 
+       e.POST("/api/video/upload", pkgedition.PostVideoUpload)
+
+       e.POST("/api/video/delete", pkgedition.PostVideoDelete)
+
+       e.GET("/api/video/c/:contentId", pkgedition.GetVideoContentByID)
+
        // stream
 
        pkgstream.InitWebRTCApi()
@@ -128,13 +147,13 @@ func RegisterRoutes(e *gin.Engine) {
 
        go pkgstream.InitRTMPServer()
 
-       e.POST("/api/video/upload", pkgstream.PostVideoUpload)
+       e.GET("/api/peers/signal/address", pkgstream.GetPeersSignalAddress)
 
-       e.GET("/api/video/c/:contentId", pkgstream.GetVideoContentByID)
+       // channel
 
-       e.GET("/api/peers/signal/address", pkgstream.GetPeersSignalAddress)
+       pkgcom.AddChannelHandler(CONF.Stream.PeerSignalAddr, pkgstream.RoomSignalHandler)
 
-       pkgstream.AddSignalHandler(CONF.Stream.PeerSignalAddr, pkgstream.RoomSignalHandler)
+       pkgcom.AddChannelCallback(pkgstream.SignalDispatcher)
 
-       go pkgstream.StartSignalHandler()
+       go pkgcom.StartAllChannelHandlers()
 }
index e5b4712c4a57b5d52966752e3f353e54a14b8a33..a3139f319cacf5a9855b8d45a5266d6e075928d0 100644 (file)
@@ -3,15 +3,54 @@ package auth
 import (
        "encoding/json"
        "fmt"
+       "net/http"
 
        "github.com/gin-gonic/contrib/sessions"
        "github.com/gin-gonic/gin"
+       "github.com/seantywork/sorrylinus-again/pkg/com"
+       "github.com/seantywork/sorrylinus-again/pkg/dbquery"
+       pkgutils "github.com/seantywork/sorrylinus-again/pkg/utils"
 )
 
 var DEBUG bool = false
 
+type UserCreate struct {
+       Passphrase      string `json:"passphrase"`
+       Id              string `json:"id"`
+       DurationSeconds int    `json:"duration_seconds"`
+}
+
+type UserLogin struct {
+       Id         string `json:"id"`
+       Passphrase string `json:"passphrase"`
+}
+
+func GenerateStateAuthCookie(c *gin.Context) string {
+
+       state, _ := pkgutils.GetRandomHex(64)
+
+       session := sessions.Default(c)
+
+       session.Set("SOLIAGAIN", state)
+       session.Save()
+
+       return state
+}
+
 func OauthGoogleLogin(c *gin.Context) {
 
+       my_key, my_type, _ := WhoAmI(c)
+
+       if my_key != "" && my_type != "" {
+
+               fmt.Printf("oauth login: already logged in\n")
+
+               c.JSON(http.StatusBadRequest, com.SERVER_RE{Status: "error", Reply: "already logged in"})
+
+               return
+
+       }
+
        oauth_state := GenerateStateAuthCookie(c)
 
        u := GoogleOauthConfig.AuthCodeURL(oauth_state)
@@ -22,6 +61,18 @@ func OauthGoogleLogin(c *gin.Context) {
 
 func OauthGoogleCallback(c *gin.Context) {
 
+       my_key, my_type, _ := WhoAmI(c)
+
+       if my_key != "" && my_type != "" {
+
+               fmt.Printf("oauth callback: already logged in\n")
+
+               c.JSON(http.StatusBadRequest, com.SERVER_RE{Status: "error", Reply: "already logged in"})
+
+               return
+
+       }
+
        session := sessions.Default(c)
 
        var session_id string
@@ -77,8 +128,230 @@ func OauthGoogleCallback(c *gin.Context) {
                return
        }
 
+       as, err := dbquery.GetByIdFromAdmin(oauth_struct.EMAIL)
+
+       if as == nil {
+
+               fmt.Printf("access auth failed: %s", err.Error())
+
+               c.Redirect(302, "/signin")
+
+               return
+
+       }
+
+       err = dbquery.MakeSessionForAdmin(session_id, oauth_struct.EMAIL)
+
+       if err != nil {
+
+               fmt.Printf("make session failed for admin: %s", err.Error())
+
+               c.Redirect(302, "/signin")
+
+               return
+
+       }
+
        fmt.Println("oauth sign in success")
 
        c.Redirect(302, "/")
 
 }
+
+func UserAdd(c *gin.Context) {
+
+       _, my_type, _ := WhoAmI(c)
+
+       if my_type != "admin" {
+
+               fmt.Printf("user add: not admin\n")
+
+               c.JSON(http.StatusForbidden, com.SERVER_RE{Status: "error", Reply: "you're not admin"})
+
+               return
+
+       }
+
+       var req com.CLIENT_REQ
+
+       var u_create UserCreate
+
+       if err := c.BindJSON(&req); err != nil {
+
+               fmt.Printf("user add: failed to bind: %s\n", err.Error())
+
+               c.JSON(http.StatusBadRequest, com.SERVER_RE{Status: "error", Reply: "invalid format"})
+
+               return
+       }
+
+       err := json.Unmarshal([]byte(req.Data), &u_create)
+
+       if err != nil {
+
+               fmt.Printf("user add: failed to unmarshal: %s\n", err.Error())
+
+               c.JSON(http.StatusBadRequest, com.SERVER_RE{Status: "error", Reply: "invalid format"})
+
+               return
+
+       }
+
+       err = dbquery.MakeUser(u_create.Id, u_create.Passphrase, u_create.DurationSeconds)
+
+       if err != nil {
+
+               fmt.Printf("user add: failed to make: %s", err.Error())
+
+               c.JSON(http.StatusInternalServerError, com.SERVER_RE{Status: "error", Reply: "failed to make user"})
+
+               return
+       }
+
+       c.JSON(http.StatusOK, com.SERVER_RE{Status: "success", Reply: fmt.Sprintf("id: %s: created", u_create.Id)})
+
+}
+
+func UserRemove(c *gin.Context) {
+
+       _, my_type, _ := WhoAmI(c)
+
+       if my_type != "admin" {
+
+               fmt.Printf("user remove: not admin\n")
+
+               c.JSON(http.StatusForbidden, com.SERVER_RE{Status: "error", Reply: "you're not admin"})
+
+               return
+
+       }
+
+       var req com.CLIENT_REQ
+
+       if err := c.BindJSON(&req); err != nil {
+
+               fmt.Printf("user add: failed to bind: %s\n", err.Error())
+
+               c.JSON(http.StatusBadRequest, com.SERVER_RE{Status: "error", Reply: "invalid format"})
+
+               return
+       }
+
+       err := dbquery.RemoveUser(req.Data)
+
+       if err != nil {
+
+               fmt.Printf("user add: failed to remove: %s", err.Error())
+
+               c.JSON(http.StatusInternalServerError, com.SERVER_RE{Status: "error", Reply: "failed to remove user"})
+
+               return
+       }
+
+       c.JSON(http.StatusOK, com.SERVER_RE{Status: "success", Reply: fmt.Sprintf("id: %s: deleted", req.Data)})
+
+}
+
+func Login(c *gin.Context) {
+
+       my_key, my_type, _ := WhoAmI(c)
+
+       if my_key != "" && my_type != "" {
+
+               fmt.Printf("user login: already logged in\n")
+
+               c.JSON(http.StatusBadRequest, com.SERVER_RE{Status: "error", Reply: "already logged in"})
+
+               return
+
+       }
+
+       var req com.CLIENT_REQ
+
+       var u_login UserLogin
+
+       if err := c.BindJSON(&req); err != nil {
+
+               fmt.Printf("user login: failed to bind: %s\n", err.Error())
+
+               c.JSON(http.StatusBadRequest, com.SERVER_RE{Status: "error", Reply: "invalid format"})
+
+               return
+       }
+
+       us, err := dbquery.GetByIdFromUser(u_login.Id)
+
+       if err != nil {
+
+               fmt.Printf("user login: failed to get from user: %s", err.Error())
+
+               c.JSON(http.StatusForbidden, com.SERVER_RE{Status: "error", Reply: "id doesn't exist"})
+
+               return
+       }
+
+       if us.Passphrase != u_login.Passphrase {
+
+               fmt.Printf("user login: passphrase: %s", "not matching")
+
+               c.JSON(http.StatusForbidden, com.SERVER_RE{Status: "error", Reply: "passphrase not matching"})
+
+               return
+
+       }
+
+       session_key := GenerateStateAuthCookie(c)
+
+       err = dbquery.MakeSessionForUser(session_key, u_login.Id, us.DurationSeconds)
+
+       if err != nil {
+
+               fmt.Printf("user login: failed to get from user: %s", err.Error())
+
+               c.JSON(http.StatusInternalServerError, com.SERVER_RE{Status: "error", Reply: "failed to login"})
+
+               return
+
+       }
+
+}
+
+func Logout(c *gin.Context) {
+
+       my_key, my_type, _ := WhoAmI(c)
+
+       if my_key == "" && my_type == "" {
+
+               fmt.Printf("user logout: not logged in\n")
+
+               c.JSON(http.StatusBadRequest, com.SERVER_RE{Status: "error", Reply: "not logged in"})
+
+               return
+
+       }
+
+       if my_type == "admin" || my_type == "user" {
+
+               err := dbquery.RemoveSessionKeyFromSession(my_key)
+
+               if err != nil {
+
+                       fmt.Printf("user logout: failed to remove session key: %s", err.Error())
+
+                       c.JSON(http.StatusInternalServerError, com.SERVER_RE{Status: "error", Reply: "failed to logout"})
+
+                       return
+
+               }
+
+       } else {
+
+               fmt.Printf("user logout: what the hell is this type?: %s", my_type)
+
+               c.JSON(http.StatusInternalServerError, com.SERVER_RE{Status: "error", Reply: "failed to logout"})
+
+               return
+
+       }
+
+}
diff --git a/pkg/auth/integrity.go b/pkg/auth/integrity.go
new file mode 100644 (file)
index 0000000..be09abf
--- /dev/null
@@ -0,0 +1,51 @@
+package auth
+
+import "unicode"
+
+func SanitizePlainNameValue(raw string) string {
+
+       var result string = ""
+
+       for _, c := range raw {
+
+               if unicode.IsLetter(c) {
+
+                       result = result + string(c)
+
+               } else if unicode.IsDigit(c) {
+
+                       result = result + string(c)
+
+               } else {
+
+                       result = result + "-"
+
+               }
+
+       }
+
+       return result
+
+}
+
+func VerifyCodeNameValue(raw string) bool {
+
+       for _, c := range raw {
+
+               if unicode.IsLetter(c) {
+
+                       continue
+
+               } else if unicode.IsDigit(c) {
+
+                       continue
+
+               } else {
+
+                       return false
+               }
+
+       }
+
+       return true
+}
index 27905d6d9440e9765ede39418062dfbbc7a9e904..c338efab3a100e442745f5beb72fe280de117e71 100644 (file)
@@ -2,16 +2,12 @@ package auth
 
 import (
        "context"
-       "crypto/rand"
-       "encoding/base64"
        "encoding/json"
        "fmt"
        "io"
        "net/http"
        "os"
 
-       "github.com/gin-gonic/contrib/sessions"
-       "github.com/gin-gonic/gin"
        "golang.org/x/oauth2"
        "golang.org/x/oauth2/google"
 )
@@ -93,21 +89,6 @@ func GenerateGoogleOauthConfig() *oauth2.Config {
 
 }
 
-func GenerateStateAuthCookie(c *gin.Context) string {
-
-       b := make([]byte, 64)
-       rand.Read(b)
-
-       state := base64.URLEncoding.EncodeToString(b)
-
-       session := sessions.Default(c)
-
-       session.Set("SOLIAGAIN", state)
-       session.Save()
-
-       return state
-}
-
 func GetUserDataFromGoogle(code string) ([]byte, error) {
 
        token, err := GoogleOauthConfig.Exchange(context.Background(), code)
diff --git a/pkg/auth/session.go b/pkg/auth/session.go
new file mode 100644 (file)
index 0000000..48ded9e
--- /dev/null
@@ -0,0 +1,50 @@
+package auth
+
+import (
+       "fmt"
+
+       "github.com/gin-gonic/contrib/sessions"
+       "github.com/gin-gonic/gin"
+       "github.com/seantywork/sorrylinus-again/pkg/dbquery"
+)
+
+func WhoAmI(c *gin.Context) (string, string, string) {
+
+       var your_key string = ""
+
+       var your_type string = ""
+
+       var your_id string = ""
+
+       session := sessions.Default(c)
+
+       var session_id string
+
+       v := session.Get("SOLIAGAIN")
+
+       if v == nil {
+
+               fmt.Printf("you: %s\n", "nobody-yet")
+               return "", "", ""
+
+       } else {
+
+               session_id = v.(string)
+
+       }
+
+       ss, err := dbquery.GetBySessionKeyFromSession(session_id)
+
+       if err != nil {
+
+               fmt.Printf("you: %s\n", "nodody-no-session")
+
+               return "", "", ""
+       }
+
+       your_key = session_id
+       your_type = ss.Type
+       your_id = ss.Id
+
+       return your_key, your_type, your_id
+}
diff --git a/pkg/com/com.go b/pkg/com/com.go
new file mode 100644 (file)
index 0000000..d56c609
--- /dev/null
@@ -0,0 +1,69 @@
+package com
+
+import (
+       "log"
+       "net/http"
+       "sync"
+
+       "github.com/gorilla/websocket"
+)
+
+type CLIENT_REQ struct {
+       Data string `json:"data"`
+}
+
+type SERVER_RE struct {
+       Status string `json:"status"`
+       Reply  string `json:"reply"`
+}
+
+var CHANNEL_ADDR string
+
+var CHANNEL_PORT string
+
+var CHANNEL_PORT_EXTERNAL string
+
+var USER_CHANNEL = make(map[string]*websocket.Conn)
+
+var CH_CALLBACKS []func()
+
+var ListLock sync.RWMutex
+
+type ThreadSafeWriter struct {
+       *websocket.Conn
+       sync.Mutex
+}
+
+func (t *ThreadSafeWriter) WriteJSON(v interface{}) error {
+       t.Lock()
+       defer t.Unlock()
+
+       return t.Conn.WriteJSON(v)
+}
+
+func AddChannelHandler(channelPath string, channelHandler func(w http.ResponseWriter, r *http.Request)) {
+
+       http.HandleFunc(channelPath, channelHandler)
+
+}
+
+func AddChannelCallback(channelFunction func()) {
+
+       CH_CALLBACKS = append(CH_CALLBACKS, channelFunction)
+}
+
+func StartAllChannelHandlers() {
+
+       callback_count := len(CH_CALLBACKS)
+
+       for i := 0; i < callback_count; i++ {
+
+               go CH_CALLBACKS[i]()
+
+       }
+
+       channel_addr := CHANNEL_ADDR + ":" + CHANNEL_PORT
+
+       log.Fatal(http.ListenAndServe(channel_addr, nil))
+
+}
index 5b2fb82d6ee7f6daac189cbe085784c94bc6a280..dd22078bea80fc843a897f1efc097954805556d1 100644 (file)
 package dbquery
 
 import (
+       "encoding/json"
        "fmt"
        "mime/multipart"
        "os"
-       "path"
+       "strings"
+       "time"
 
        "github.com/gin-gonic/gin"
 )
 
+type AdminStruct struct {
+}
+
+type UserStruct struct {
+       Passphrase      string `json:"passphrase"`
+       DurationSeconds int    `json:"duration_seconds"`
+}
+
+type SessionStruct struct {
+       Type            string `json:"type"`
+       Id              string `json:"id"`
+       StartTime       string `json:"start_time"`
+       DurationSeconds int    `json:"duration_seconds"`
+}
+
+type MediaStruct struct {
+       ISPublic  bool     `json:"is_public"`
+       Type      string   `json:"type"`
+       Extension string   `json:"extension"`
+       PlainName string   `json:"plain_name"`
+       AllowedId []string `json:"allowed_id"`
+}
+
+var adminPath string = "./data/admin/"
+
+var userPath string = "./data/user/"
+
+var sessionPath string = "./data/session/"
+
 var mediaPath string = "./data/media/"
 
-var videoPath string = "./data/media_video/"
+var articlePath string = "./data/media/article/"
+
+var imagePath string = "./data/media/image/"
+
+var videoPath string = "./data/media/video/"
+
+func GetByIdFromAdmin(email string) (*AdminStruct, error) {
+
+       var as AdminStruct
+
+       this_file_path := adminPath + email + ".json"
+
+       file_b, err := os.ReadFile(this_file_path)
+
+       if err != nil {
+
+               return nil, fmt.Errorf("failed to get from admin: %s", err.Error())
+       }
+
+       err = json.Unmarshal(file_b, &as)
+
+       if err != nil {
+
+               return nil, fmt.Errorf("failed to get from admin: %s", err.Error())
+       }
+
+       return &as, nil
+
+}
+
+func GetByIdFromUser(id string) (*UserStruct, error) {
+
+       var us UserStruct
+
+       this_file_path := userPath + id + ".json"
+
+       file_b, err := os.ReadFile(this_file_path)
+
+       if err != nil {
+
+               return nil, fmt.Errorf("failed to get from user: %s", err.Error())
+
+       }
+
+       err = json.Unmarshal(file_b, &us)
+
+       if err != nil {
+
+               return nil, fmt.Errorf("failed to get from user: %s", err.Error())
+       }
+
+       return &us, nil
+
+}
+
+func GetBySessionKeyFromSession(session_key string) (*SessionStruct, error) {
+
+       var ss SessionStruct
+
+       this_file_path := sessionPath + session_key + ".json"
+
+       file_b, err := os.ReadFile(this_file_path)
+
+       if err != nil {
+
+               return nil, fmt.Errorf("session pool: failed to read file: %s", err.Error())
+
+       }
+
+       err = json.Unmarshal(file_b, &ss)
+
+       if err != nil {
+
+               return nil, fmt.Errorf("session pool: failed to marshal: %s", err.Error())
+
+       }
+
+       t_now := time.Now()
+
+       t, _ := time.Parse("2006-01-02-15-04-05", ss.StartTime)
+
+       diff := t_now.Sub(t)
+
+       if ss.DurationSeconds == 0 || (diff.Seconds() < float64(ss.DurationSeconds)) {
+
+               return &ss, nil
+
+       } else {
+
+               err = RemoveSessionKeyFromSession(session_key)
+
+               if err != nil {
+
+                       return nil, fmt.Errorf("session: failed to remove: %s", err.Error())
+
+               }
 
-func UploadVideo(c *gin.Context, file *multipart.FileHeader, filename string, new_filename string) error {
+               return nil, fmt.Errorf("id: %s: expired", ss.Id)
 
-       /*
+       }
+
+}
+
+func GetByMediaKeyFromMedia(media_key string) (*MediaStruct, error) {
+
+       var ms MediaStruct
+
+       this_file_path := mediaPath + media_key + ".json"
+
+       file_b, err := os.ReadFile(this_file_path)
+
+       if err != nil {
 
-               TODO:
-                       save media index
+               return nil, fmt.Errorf("media: failed to read file: %s", err.Error())
 
-       */
+       }
+
+       err = json.Unmarshal(file_b, &ms)
+
+       if err != nil {
+
+               return nil, fmt.Errorf("media: failed to marshal: %s", err.Error())
+       }
+
+       return &ms, nil
+
+}
 
-       upload_path := path.Join(videoPath, new_filename)
+func GetByIdFromSession(email string) (string, *SessionStruct, error) {
 
-       err := c.SaveUploadedFile(file, upload_path)
+       files, err := os.ReadDir(sessionPath)
+
+       if err != nil {
+
+               return "", nil, fmt.Errorf("session pool: failed to read dir: %s", err.Error())
+
+       }
+
+       for _, f := range files {
+
+               ss := SessionStruct{}
+
+               f_name := f.Name()
+
+               if !strings.Contains(f_name, ".json") {
+                       continue
+               }
+
+               key_name := strings.ReplaceAll(f_name, ".json", "")
+
+               this_file_path := sessionPath + f_name
+
+               file_b, err := os.ReadFile(this_file_path)
+
+               if err != nil {
+
+                       return "", nil, fmt.Errorf("session pool: failed to read file: %s", err.Error())
+
+               }
+
+               err = json.Unmarshal(file_b, &ss)
+
+               if err != nil {
+
+                       return "", nil, fmt.Errorf("session pool: failed to marshal: %s", err.Error())
+               }
+
+               t_now := time.Now()
+
+               t, _ := time.Parse("2006-01-02-15-04-05", ss.StartTime)
+
+               diff := t_now.Sub(t)
+
+               if ss.Id == email {
+
+                       if ss.DurationSeconds == 0 || (diff.Seconds() < float64(ss.DurationSeconds)) {
+
+                               return key_name, &ss, nil
+
+                       } else {
+
+                               err = RemoveSessionKeyFromSession(key_name)
+
+                               if err != nil {
+
+                                       return "", nil, fmt.Errorf("session pool: failed to remove: %s", err.Error())
+
+                               }
+
+                               return "", nil, fmt.Errorf("id: %s: expired", email)
+
+                       }
+
+               }
+
+       }
+
+       return "", nil, fmt.Errorf("id: %s: not found", email)
+}
+
+func RemoveSessionKeyFromSession(session_key string) error {
+
+       this_file_path := sessionPath + session_key + ".json"
+
+       err := os.Remove(this_file_path)
+
+       if err != nil {
+
+               return err
+
+       }
+
+       return nil
+}
+
+func MakeSessionForAdmin(session_key string, email string) error {
+
+       _, ss, _ := GetByIdFromSession(email)
+
+       if ss != nil {
+
+               return fmt.Errorf("valid session already exists for: %s", email)
+
+       }
+
+       new_ss := SessionStruct{}
+
+       t_now := time.Now()
+
+       t_str := t_now.Format("2006-01-02-15-04-05")
+
+       new_ss.Type = "admin"
+
+       new_ss.Id = email
+
+       new_ss.StartTime = t_str
+
+       new_ss.DurationSeconds = 0
+
+       jb, err := json.Marshal(new_ss)
+
+       if err != nil {
+
+               return fmt.Errorf("failed to marshal new session admin: %s", err.Error())
+       }
+
+       this_file_path := sessionPath + session_key + ".json"
+
+       err = os.WriteFile(this_file_path, jb, 0644)
+
+       if err != nil {
+
+               return fmt.Errorf("failed to write new session admin: %s", err.Error())
+       }
+
+       return nil
+}
+
+func MakeUser(id string, passphrase string, duration_seconds int) error {
+
+       var us UserStruct
+
+       this_file_path := userPath + id + ".json"
+
+       if _, err := os.Stat(this_file_path); err == nil {
+
+               return fmt.Errorf("id: %s: exists", err.Error())
+
+       }
+
+       us.Passphrase = passphrase
+
+       us.DurationSeconds = duration_seconds
+
+       jb, err := json.Marshal(us)
+
+       if err != nil {
+
+               return fmt.Errorf("failed to make user: %s", err.Error())
+
+       }
+
+       err = os.WriteFile(this_file_path, jb, 0644)
+
+       if err != nil {
+
+               return fmt.Errorf("failed to make user: %s", err.Error())
+       }
+
+       return nil
+}
+
+func RemoveUser(id string) error {
+
+       this_file_path := userPath + id + ".json"
+
+       key, ss, _ := GetByIdFromSession(id)
+
+       if ss == nil {
+
+               fmt.Println("remove user: existing session removed")
+
+               _ = RemoveSessionKeyFromSession(key)
+
+       }
+
+       err := os.Remove(this_file_path)
+
+       if err != nil {
+
+               return err
+
+       }
+
+       return nil
+}
+
+func MakeSessionForUser(session_key string, id string, duration_seconds int) error {
+
+       var ss SessionStruct
+
+       this_file_path := sessionPath + session_key + ".json"
+
+       t_now := time.Now()
+
+       t_str := t_now.Format("2006-01-02-15-04-05")
+
+       ss.Type = "user"
+
+       ss.Id = id
+
+       ss.StartTime = t_str
+
+       ss.DurationSeconds = duration_seconds
+
+       jb, err := json.Marshal(ss)
+
+       if err != nil {
+
+               return fmt.Errorf("failed to make session for user: %s", err.Error())
+
+       }
+
+       err = os.WriteFile(this_file_path, jb, 0644)
+
+       if err != nil {
+
+               return fmt.Errorf("failed to make session: %s", err.Error())
+
+       }
+
+       return nil
+}
+
+func UploadVideo(c *gin.Context, file *multipart.FileHeader, filename string, new_filename string, extension string) error {
+
+       ms := MediaStruct{}
+
+       this_file_path := mediaPath + new_filename + ".json"
+
+       this_video_path := videoPath + new_filename + "." + extension
+
+       ms.ISPublic = true
+       ms.Type = "video"
+       ms.PlainName = filename
+       ms.Extension = extension
+
+       jb, err := json.Marshal(ms)
 
        if err != nil {
 
                return fmt.Errorf("failed to upload: %s", err.Error())
        }
 
+       err = os.WriteFile(this_file_path, jb, 0644)
+
+       if err != nil {
+
+               return fmt.Errorf("failed to upload: %s", err.Error())
+       }
+
+       err = c.SaveUploadedFile(file, this_video_path)
+
+       if err != nil {
+
+               return fmt.Errorf("failed to upload: %s", err.Error())
+       }
+
+       return nil
+}
+
+func DeleteVideo(media_key string) error {
+
+       var ms MediaStruct
+
+       this_file_path := mediaPath + media_key + ".json"
+
+       file_b, err := os.ReadFile(this_file_path)
+
+       if err != nil {
+
+               return fmt.Errorf("failed to delete video: %s", err.Error())
+
+       }
+
+       err = json.Unmarshal(file_b, &ms)
+
+       if err != nil {
+
+               return fmt.Errorf("failed to delete video: marshal: %s", err.Error())
+       }
+
+       this_video_path := videoPath + media_key + "." + ms.Extension
+
+       err = os.Remove(this_video_path)
+
+       if err != nil {
+
+               return fmt.Errorf("failed to delete video: rmvid: %s", err.Error())
+       }
+
+       err = os.Remove(this_file_path)
+
+       if err != nil {
+
+               return fmt.Errorf("failed to delete video: rmmd: %s", err.Error())
+       }
+
        return nil
 }
 
 func DownloadVideo(c *gin.Context, watchId string) error {
 
-       download_path := path.Join(videoPath, watchId)
+       ms, err := GetByMediaKeyFromMedia(watchId)
+
+       if ms == nil {
+
+               return fmt.Errorf("failed to download video: %s", err.Error())
+
+       }
+
+       if ms.Type != "video" {
+
+               return fmt.Errorf("failed to download video: %s: %s", "wrong type", ms.Type)
+       }
+
+       this_video_path := videoPath + watchId + "." + ms.Extension
 
-       if _, err := os.Stat(download_path); err != nil {
+       if _, err := os.Stat(this_video_path); err != nil {
 
                return err
 
        }
 
-       c.Header("Content-Type", "video/mp4")
+       c.Header("Content-Type", "video/"+ms.Extension)
 
-       c.File(download_path)
+       c.File(this_video_path)
 
        return nil
 }
diff --git a/pkg/edition/edition_video.go b/pkg/edition/edition_video.go
new file mode 100644 (file)
index 0000000..c8725b9
--- /dev/null
@@ -0,0 +1,164 @@
+package edition
+
+import (
+       "fmt"
+       "net/http"
+       "strings"
+
+       "github.com/gin-gonic/gin"
+       pkgauth "github.com/seantywork/sorrylinus-again/pkg/auth"
+       "github.com/seantywork/sorrylinus-again/pkg/com"
+       "github.com/seantywork/sorrylinus-again/pkg/dbquery"
+       pkgdbq "github.com/seantywork/sorrylinus-again/pkg/dbquery"
+       pkgutils "github.com/seantywork/sorrylinus-again/pkg/utils"
+)
+
+var EXTENSION_ALLOWLIST []string
+
+func PostVideoUpload(c *gin.Context) {
+
+       _, my_type, _ := pkgauth.WhoAmI(c)
+
+       if my_type != "admin" {
+
+               fmt.Printf("video upload: not admin\n")
+
+               c.JSON(http.StatusForbidden, com.SERVER_RE{Status: "error", Reply: "you're not admin"})
+
+               return
+
+       }
+
+       file, _ := c.FormFile("file")
+
+       f_name := file.Filename
+
+       f_name_list := strings.Split(f_name, ".")
+
+       f_name_len := len(f_name_list)
+
+       if f_name_len < 1 {
+
+               fmt.Println("no extension specified")
+
+               c.JSON(http.StatusBadRequest, com.SERVER_RE{Status: "error", Reply: "invalid format"})
+
+               return
+       }
+
+       v_fname := pkgauth.SanitizePlainNameValue(f_name_list[0])
+
+       extension := f_name_list[f_name_len-1]
+
+       if !pkgutils.CheckIfSliceContains[string](EXTENSION_ALLOWLIST, extension) {
+
+               fmt.Println("extension not allowed")
+
+               c.JSON(http.StatusBadRequest, com.SERVER_RE{Status: "error", Reply: "invalid format"})
+
+               return
+
+       }
+
+       fmt.Printf("received: %s, size: %d\n", file.Filename, file.Size)
+
+       file_name, _ := pkgutils.GetRandomHex(32)
+
+       err := pkgdbq.UploadVideo(c, file, v_fname, file_name, extension)
+
+       if err != nil {
+
+               fmt.Println(err.Error())
+
+               c.JSON(http.StatusInternalServerError, com.SERVER_RE{Status: "error", Reply: "failed to save"})
+
+               return
+
+       }
+
+       c.JSON(http.StatusOK, com.SERVER_RE{Status: "success", Reply: "uploaded"})
+
+}
+
+func PostVideoDelete(c *gin.Context) {
+
+       _, my_type, _ := pkgauth.WhoAmI(c)
+
+       if my_type != "admin" {
+
+               fmt.Printf("video delete: not admin\n")
+
+               c.JSON(http.StatusForbidden, com.SERVER_RE{Status: "error", Reply: "you're not admin"})
+
+               return
+
+       }
+
+       fmt.Println("delete video")
+
+       var req com.CLIENT_REQ
+
+       if err := c.BindJSON(&req); err != nil {
+
+               fmt.Printf("video delete: failed to bind: %s\n", err.Error())
+
+               c.JSON(http.StatusBadRequest, com.SERVER_RE{Status: "error", Reply: "invalid format"})
+
+               return
+       }
+
+       if !pkgauth.VerifyCodeNameValue(req.Data) {
+
+               fmt.Printf("video name verification failed: %s\n", req.Data)
+
+               c.JSON(http.StatusBadRequest, com.SERVER_RE{Status: "error", Reply: "invalid format"})
+
+               return
+
+       }
+
+       err := dbquery.DeleteVideo(req.Data)
+
+       if err != nil {
+
+               fmt.Printf("video delete: %s\n", err.Error())
+
+               c.JSON(http.StatusInternalServerError, com.SERVER_RE{Status: "error", Reply: "failed delete"})
+
+               return
+
+       }
+
+       c.JSON(http.StatusOK, com.SERVER_RE{Status: "success", Reply: "deleted"})
+
+}
+
+func GetVideoContentByID(c *gin.Context) {
+
+       watchId := c.Param("contentId")
+
+       if !pkgauth.VerifyCodeNameValue(watchId) {
+
+               fmt.Printf("download video: illegal: %s\n", watchId)
+
+               c.JSON(http.StatusBadRequest, com.SERVER_RE{Status: "error", Reply: "invalid format"})
+
+               return
+
+       }
+
+       err := pkgdbq.DownloadVideo(c, watchId)
+
+       if err != nil {
+
+               fmt.Printf("download video: %s\n", err.Error())
+
+               c.JSON(http.StatusBadRequest, com.SERVER_RE{Status: "error", Reply: "invalid format"})
+
+               return
+
+       }
+
+       fmt.Println("download success")
+
+}
index 0cdc0c5020ed8e5eac2897b79b9855f375f57963..46bf8159c22d271513c1975e08e237c637f99002 100644 (file)
@@ -1,70 +1,32 @@
 package stream
 
 import (
-       "log"
-       "net/http"
-       "sync"
        "time"
 
        "github.com/gorilla/websocket"
        "github.com/pion/webrtc/v4"
+       ch "github.com/seantywork/sorrylinus-again/pkg/com"
 )
 
-var SIGNAL_ADDR string
-
-var SIGNAL_PORT string
-
-var SIGNAL_PORT_EXTERNAL string
-
-var USER_SIGNAL = make(map[string]*websocket.Conn)
-
-var UPGRADER = websocket.Upgrader{}
-
 type SIGNAL_INFO struct {
        Command string `json:"command"`
        Status  string `json:"status"`
        Data    string `json:"data"`
 }
 
-var listLock sync.RWMutex
+var UPGRADER = websocket.Upgrader{}
+
 var peerConnections = make([]peerConnectionState, 0)
 var trackLocals = make(map[string]*webrtc.TrackLocalStaticRTP)
 
 type peerConnectionState struct {
        peerConnection *webrtc.PeerConnection
-       websocket      *threadSafeWriter
-}
-
-type threadSafeWriter struct {
-       *websocket.Conn
-       sync.Mutex
-}
-
-func (t *threadSafeWriter) WriteJSON(v interface{}) error {
-       t.Lock()
-       defer t.Unlock()
-
-       return t.Conn.WriteJSON(v)
-}
-
-func AddSignalHandler(signalPath string, signalHandler func(w http.ResponseWriter, r *http.Request)) {
-
-       http.HandleFunc(signalPath, signalHandler)
-
+       websocket      *ch.ThreadSafeWriter
 }
 
-func StartSignalHandler() {
-
-       go func() {
-
-               for range time.NewTicker(time.Second * 3).C {
-                       dispatchKeyFrame()
-               }
-
-       }()
-
-       signal_addr := SIGNAL_ADDR + ":" + SIGNAL_PORT
-
-       log.Fatal(http.ListenAndServe(signal_addr, nil))
+func SignalDispatcher() {
 
+       for range time.NewTicker(time.Second * 3).C {
+               dispatchKeyFrame()
+       }
 }
index c6ac578082b38dbc27815d531c240e0914844085..2f4e905eeb6e0eaf9df878f2175fb98bd9f24d21 100644 (file)
@@ -12,17 +12,9 @@ import (
        "github.com/pion/ice/v3"
        "github.com/pion/rtcp"
        "github.com/pion/webrtc/v4"
+       "github.com/seantywork/sorrylinus-again/pkg/com"
 )
 
-type CLIENT_REQ struct {
-       Data string `json:"data"`
-}
-
-type SERVER_RE struct {
-       Status string `json:"status"`
-       Reply  string `json:"reply"`
-}
-
 var EXTERNAL_URL string
 
 var INTERNAL_URL string
@@ -49,10 +41,10 @@ func GetTurnServeAddr(c *gin.Context) {
 
        if err != nil {
 
-               c.JSON(http.StatusOK, SERVER_RE{Status: "failed", Reply: "error"})
+               c.JSON(http.StatusOK, com.SERVER_RE{Status: "failed", Reply: "error"})
        }
 
-       c.JSON(http.StatusOK, SERVER_RE{Status: "success", Reply: string(data_b)})
+       c.JSON(http.StatusOK, com.SERVER_RE{Status: "success", Reply: string(data_b)})
 
 }
 
@@ -153,9 +145,9 @@ func createTrack(peerConnection *webrtc.PeerConnection,
 }
 
 func addTrack(t *webrtc.TrackRemote) *webrtc.TrackLocalStaticRTP {
-       listLock.Lock()
+       com.ListLock.Lock()
        defer func() {
-               listLock.Unlock()
+               com.ListLock.Unlock()
                signalPeerConnections()
        }()
 
@@ -169,9 +161,9 @@ func addTrack(t *webrtc.TrackRemote) *webrtc.TrackLocalStaticRTP {
 }
 
 func removeTrack(t *webrtc.TrackLocalStaticRTP) {
-       listLock.Lock()
+       com.ListLock.Lock()
        defer func() {
-               listLock.Unlock()
+               com.ListLock.Unlock()
                signalPeerConnections()
        }()
 
index 7f403dde9283b3ba026af61e5978807b6fe5ecb4..0703e4f7dcfc730eeb86766cc42a399bda7c7953 100644 (file)
@@ -10,11 +10,12 @@ import (
        "net"
        "time"
 
-       "github.com/OKESTRO-AIDevOps/nkia/pkg/utils"
        "github.com/gin-gonic/gin"
        "github.com/pion/webrtc/v4"
        "github.com/pion/webrtc/v4/pkg/media"
        "github.com/pkg/errors"
+       "github.com/seantywork/sorrylinus-again/pkg/com"
+       "github.com/seantywork/sorrylinus-again/pkg/utils"
        flvtag "github.com/yutopp/go-flv/tag"
        "github.com/yutopp/go-rtmp"
        rtmpmsg "github.com/yutopp/go-rtmp/message"
@@ -90,7 +91,7 @@ func PostCCTVCreate(c *gin.Context) {
                panic(err)
        }
 
-       var req CLIENT_REQ
+       var req com.CLIENT_REQ
 
        var offer webrtc.SessionDescription
 
@@ -120,7 +121,7 @@ func PostCCTVCreate(c *gin.Context) {
        }
        <-gatherComplete
 
-       streamingKey, err := utils.RandomHex(16)
+       streamingKey, err := utils.GetRandomHex(16)
 
        if err != nil {
 
@@ -148,7 +149,7 @@ func PostCCTVCreate(c *gin.Context) {
                panic(err)
        }
 
-       var resp SERVER_RE
+       var resp com.SERVER_RE
 
        resp.Status = "success"
        resp.Reply = string(desc_b)
@@ -166,7 +167,7 @@ func PostCCTVDelete(c *gin.Context) {
 
        */
 
-       var resp SERVER_RE
+       var resp com.SERVER_RE
 
        resp.Status = "success"
        resp.Reply = ""
index a561a549dde68db6e03327f898a66b5feb0e1e43..549fdd96ed602956d62acc9f7ed39eb51a4e4105 100644 (file)
@@ -10,6 +10,7 @@ import (
        "github.com/gin-gonic/gin"
        "github.com/pion/rtcp"
        "github.com/pion/webrtc/v4"
+       "github.com/seantywork/sorrylinus-again/pkg/com"
        pkgutils "github.com/seantywork/sorrylinus-again/pkg/utils"
 )
 
@@ -17,9 +18,9 @@ var PEERS_SIGNAL_PATH string
 
 func GetPeersSignalAddress(c *gin.Context) {
 
-       s_addr := EXTERNAL_URL + ":" + SIGNAL_PORT_EXTERNAL + PEERS_SIGNAL_PATH
+       s_addr := EXTERNAL_URL + ":" + com.CHANNEL_PORT_EXTERNAL + PEERS_SIGNAL_PATH
 
-       c.JSON(http.StatusOK, SERVER_RE{Status: "success", Reply: s_addr})
+       c.JSON(http.StatusOK, com.SERVER_RE{Status: "success", Reply: s_addr})
 
 }
 
@@ -34,7 +35,7 @@ func RoomSignalHandler(w http.ResponseWriter, r *http.Request) {
                return
        }
 
-       c := &threadSafeWriter{unsafeConn, sync.Mutex{}}
+       c := &com.ThreadSafeWriter{unsafeConn, sync.Mutex{}}
 
        // When this frame returns close the Websocket
        defer c.Close() //nolint
@@ -71,9 +72,9 @@ func RoomSignalHandler(w http.ResponseWriter, r *http.Request) {
        }
 
        // Add our new PeerConnection to global list
-       listLock.Lock()
+       com.ListLock.Lock()
        peerConnections = append(peerConnections, peerConnectionState{peerConnection, c})
-       listLock.Unlock()
+       com.ListLock.Unlock()
 
        // Trickle ICE. Emit server candidate to client
        peerConnection.OnICECandidate(func(i *webrtc.ICECandidate) {
@@ -188,8 +189,8 @@ func RoomSignalHandler(w http.ResponseWriter, r *http.Request) {
 }
 
 func dispatchKeyFrame() {
-       listLock.Lock()
-       defer listLock.Unlock()
+       com.ListLock.Lock()
+       defer com.ListLock.Unlock()
 
        for i := range peerConnections {
                for _, receiver := range peerConnections[i].peerConnection.GetReceivers() {
@@ -207,10 +208,10 @@ func dispatchKeyFrame() {
 }
 
 func signalPeerConnections() {
-       listLock.Lock()
+       com.ListLock.Lock()
 
        defer func() {
-               listLock.Unlock()
+               com.ListLock.Unlock()
                dispatchKeyFrame()
        }()
 
diff --git a/pkg/stream/stream_video.go b/pkg/stream/stream_video.go
deleted file mode 100644 (file)
index 4b61b42..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-package stream
-
-import (
-       "fmt"
-       "net/http"
-       "strings"
-
-       "github.com/gin-gonic/gin"
-       pkgdbq "github.com/seantywork/sorrylinus-again/pkg/dbquery"
-       pkgutils "github.com/seantywork/sorrylinus-again/pkg/utils"
-)
-
-var EXTENSION_ALLOWLIST []string
-
-func PostVideoUpload(c *gin.Context) {
-
-       file, _ := c.FormFile("file")
-
-       f_name := file.Filename
-
-       f_name_list := strings.Split(f_name, ".")
-
-       f_name_len := len(f_name_list)
-
-       if f_name_len < 1 {
-
-               fmt.Println("no extension specified")
-
-               c.JSON(http.StatusBadRequest, SERVER_RE{Status: "error", Reply: "invalid format"})
-
-               return
-       }
-
-       extension := f_name_list[f_name_len-1]
-
-       if !pkgutils.CheckIfSliceContains[string](f_name_list, extension) {
-
-               fmt.Println("extension not allowed")
-
-               c.JSON(http.StatusBadRequest, SERVER_RE{Status: "error", Reply: "invalid format"})
-
-               return
-
-       }
-
-       fmt.Printf("received: %s, size: %d\n", file.Filename, file.Size)
-
-       file_name, _ := pkgutils.GetRandomHex(32)
-
-       err := pkgdbq.UploadVideo(c, file, f_name, file_name+"."+extension)
-
-       if err != nil {
-
-               fmt.Println(err.Error())
-
-               c.JSON(http.StatusInternalServerError, SERVER_RE{Status: "error", Reply: "failed to save"})
-
-               return
-
-       }
-
-       c.JSON(http.StatusOK, SERVER_RE{Status: "success", Reply: "uploaded"})
-
-}
-
-func GetVideoContentByID(c *gin.Context) {
-
-       watchId := c.Param("contentId")
-
-       err := pkgdbq.DownloadVideo(c, watchId)
-
-       if err != nil {
-
-               fmt.Println("path doesn't exist")
-
-               c.JSON(http.StatusBadRequest, SERVER_RE{Status: "error", Reply: "invalid format"})
-
-               return
-
-       }
-
-       fmt.Println("download success")
-
-}
diff --git a/view/content/peers.html b/view/content/peers.html
deleted file mode 100644 (file)
index 4a55c63..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-
-    <meta charset="utf-8">
-    <title>peers</title>
-    <!--<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>-->
-    <!--<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>-->
-
-  </head>
-  <body>
-    <h3> Local Video </h3>
-    <video id="localVideo" width="160" height="120" autoplay muted></video> <br />
-
-    <h3> Remote Video </h3>
-    <div id="remoteVideos"></div> <br />
-
-    <h3> Logs </h3>
-    <div id="logs"></div>
-
-
-    <button onclick="initPeers()">Join</button>
-
-
-  </body>
-
-  <script src="/public/js/peers.js"></script>
-</html>
\ No newline at end of file
diff --git a/view/etc/cctv_local.html b/view/etc/cctv_local.html
new file mode 100644 (file)
index 0000000..43b6a8b
--- /dev/null
@@ -0,0 +1,35 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>webrtc client</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <link rel="icon" type="image/x-icon" href="favicon.ico">
+
+    <!--<link rel="stylesheet" href="/public/css/cctv_local.css">-->
+    <!--<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>-->
+
+    <script src="/public/js/cctv_local.js"></script>
+
+</head>
+<body>
+    Browser base64 Session Description<br />
+    <textarea id="localSessionDescription" readonly="true"></textarea> <br />
+
+    <button onclick="startCCTVOffer()"> Start offer </button><br />
+    
+    Golang base64 Session Description<br />
+    <textarea id="remoteSessionDescription"> </textarea> <br/>
+    <button onclick="startSession()"> Start Session </button><br />
+    
+    <br />
+    
+    Video<br />
+    <div id="remoteVideos"></div> <br />
+    
+    Logs<br />
+    <div id="div"></div>
+    
+</body>
+
+</html>
\ No newline at end of file
diff --git a/view/etc/peers_p2p.html b/view/etc/peers_p2p.html
new file mode 100644 (file)
index 0000000..1a27c2b
--- /dev/null
@@ -0,0 +1,41 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <title>webrtc client</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <link rel="icon" type="image/x-icon" href="favicon.ico">
+
+    <link rel="stylesheet" href="/public/css/peers_p2p.css">
+
+    <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
+    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
+
+</head>
+<body>
+
+    <label for="mid">meeting ID</label>
+    <input type="text" id="mid" name="mid"><br><br>
+    <label for="uid">user ID</label>
+    <input type="text" id="uid" name="uid"><br><br>
+    <button onclick="initPeers()" class="start-call">
+        Init the call!
+    </button>
+
+
+    <button onclick="startCall()" class="start-call">
+        Start the call!
+    </button>
+
+    <div id="peer-receive"></div>
+
+    <div id="peer-send">
+        <video autoplay id="senderVideo" width="500" height="500" controls muted preload="none"></video>
+    </div>
+
+
+</body>
+
+<script src="/public/js/peers.js"></script>
+
+</html>
\ No newline at end of file
diff --git a/view/mypage.html b/view/mypage.html
deleted file mode 100644 (file)
index d5d408a..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<html>
-  <head>
-    <title> mypage </title>
-    <!--<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>-->
-  </head>
-
-  <body>
-    <h1> RTMP to WebRTC </h1>
-    <div id="rtmpFeed"></div>
-
-    <button onclick="initCCTV()"> start cctv </button>
-    
-    <form action="/video/upload" method="post" enctype="multipart/form-data">
-      <label for="file">File</label>
-      <input id="file" name="file" type="file" />
-      <button>Upload</button>
-    </form>
-
-
-  </body>
-
-  <script src="/public/js/cctv.js"></script>
-  <script src="/public/js/video.js"></script>
-
-</html>
\ No newline at end of file
diff --git a/view/mypage/article.html b/view/mypage/article.html
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/view/mypage/index.html b/view/mypage/index.html
new file mode 100644 (file)
index 0000000..54fb428
--- /dev/null
@@ -0,0 +1,19 @@
+<html>
+  <head>
+    <title> mypage </title>
+    <!--<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>-->
+  </head>
+
+  <body>
+    <h1> RTMP to WebRTC </h1>
+    <div id="rtmpFeed"></div>
+
+    <button onclick="initCCTV()"> start cctv </button>
+    
+
+  </body>
+
+  <script src="/public/js/cctv.js"></script>
+
+
+</html>
\ No newline at end of file
diff --git a/view/mypage/room.html b/view/mypage/room.html
new file mode 100644 (file)
index 0000000..bb62f84
--- /dev/null
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+  <head>
+
+    <meta charset="utf-8">
+    <title>mypage room</title>
+    <!--<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>-->
+    <!--<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>-->
+
+  </head>
+  <body>
+    <h3> Local Video </h3>
+    <video id="localVideo" width="160" height="120" autoplay muted></video> <br />
+
+    <h3> Remote Video </h3>
+    <div id="remoteVideos"></div> <br />
+
+    <h3> Logs </h3>
+    <div id="logs"></div>
+
+
+    <button onclick="initPeers()">Join</button>
+
+
+  </body>
+
+  <script src="/public/js/peers.js"></script>
+</html>
\ No newline at end of file
diff --git a/view/mypage/video.html b/view/mypage/video.html
new file mode 100644 (file)
index 0000000..e600073
--- /dev/null
@@ -0,0 +1,21 @@
+<html>
+  <head>
+    <title> mypage video </title>
+    <!--<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>-->
+  </head>
+
+  <body>
+
+    <form action="/video/upload" method="post" enctype="multipart/form-data">
+      <label for="file">File</label>
+      <input id="file" name="file" type="file" />
+      <button>Upload</button>
+    </form>
+
+
+  </body>
+
+
+  <script src="/public/js/video.js"></script>
+
+</html>
\ No newline at end of file
diff --git a/view/org/cctv_local.html b/view/org/cctv_local.html
deleted file mode 100644 (file)
index 43b6a8b..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<!doctype html>
-<html lang="en">
-<head>
-    <meta charset="utf-8">
-    <title>webrtc client</title>
-    <meta name="viewport" content="width=device-width, initial-scale=1">
-    <link rel="icon" type="image/x-icon" href="favicon.ico">
-
-    <!--<link rel="stylesheet" href="/public/css/cctv_local.css">-->
-    <!--<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>-->
-
-    <script src="/public/js/cctv_local.js"></script>
-
-</head>
-<body>
-    Browser base64 Session Description<br />
-    <textarea id="localSessionDescription" readonly="true"></textarea> <br />
-
-    <button onclick="startCCTVOffer()"> Start offer </button><br />
-    
-    Golang base64 Session Description<br />
-    <textarea id="remoteSessionDescription"> </textarea> <br/>
-    <button onclick="startSession()"> Start Session </button><br />
-    
-    <br />
-    
-    Video<br />
-    <div id="remoteVideos"></div> <br />
-    
-    Logs<br />
-    <div id="div"></div>
-    
-</body>
-
-</html>
\ No newline at end of file
diff --git a/view/org/peers_p2p.html b/view/org/peers_p2p.html
deleted file mode 100644 (file)
index 1a27c2b..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-<!doctype html>
-<html lang="en">
-<head>
-    <meta charset="utf-8">
-    <title>webrtc client</title>
-    <meta name="viewport" content="width=device-width, initial-scale=1">
-    <link rel="icon" type="image/x-icon" href="favicon.ico">
-
-    <link rel="stylesheet" href="/public/css/peers_p2p.css">
-
-    <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
-    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
-
-</head>
-<body>
-
-    <label for="mid">meeting ID</label>
-    <input type="text" id="mid" name="mid"><br><br>
-    <label for="uid">user ID</label>
-    <input type="text" id="uid" name="uid"><br><br>
-    <button onclick="initPeers()" class="start-call">
-        Init the call!
-    </button>
-
-
-    <button onclick="startCall()" class="start-call">
-        Start the call!
-    </button>
-
-    <div id="peer-receive"></div>
-
-    <div id="peer-send">
-        <video autoplay id="senderVideo" width="500" height="500" controls muted preload="none"></video>
-    </div>
-
-
-</body>
-
-<script src="/public/js/peers.js"></script>
-
-</html>
\ No newline at end of file
diff --git a/view/room/index.html b/view/room/index.html
new file mode 100644 (file)
index 0000000..4a55c63
--- /dev/null
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+  <head>
+
+    <meta charset="utf-8">
+    <title>peers</title>
+    <!--<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>-->
+    <!--<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>-->
+
+  </head>
+  <body>
+    <h3> Local Video </h3>
+    <video id="localVideo" width="160" height="120" autoplay muted></video> <br />
+
+    <h3> Remote Video </h3>
+    <div id="remoteVideos"></div> <br />
+
+    <h3> Logs </h3>
+    <div id="logs"></div>
+
+
+    <button onclick="initPeers()">Join</button>
+
+
+  </body>
+
+  <script src="/public/js/peers.js"></script>
+</html>
\ No newline at end of file